Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- TwoBearsBots
- Optimization enabled
- false
- Compiler version
- v0.8.16+commit.07a7930e
- EVM Version
- default
- Verified at
- 2024-09-26T15:35:02.623574Z
Contract source code
// All rights reserved. // SPDX-License-Identifier: No License (None) pragma solidity ^0.8.16; interface IContractBotsHelp { function checkApproveAndBalance(address _owner, address _token_in, uint _value_in, uint _value_inc_balance) external view returns (uint8); function checkCreateBotSellBuy(address _owner, address _token_in, address _token_out, uint _value, uint _value_inc, uint _price, uint _price_step, uint _price_limit) external view returns (uint8, uint8, uint256, uint256); function checkCreateBotNetTrade(address _owner, address _token_in, address _token_out, uint _value_sell, uint _value_buy, uint _price, uint _price_step, uint _price_up_limit, uint _price_down_limit) external view returns (uint8, uint256, uint256); function checkSchemeBotSellBuy(address _owner, address _token_in, address _token_out, uint _value, uint _price, uint _price_limit) external view returns (uint8, uint256, uint256); function checkSchemeBotNetTrade(address _owner, address _token_in, address _token_out, uint[] memory _param, uint[] memory _order_data, uint[] memory _order_data_2) external view returns (uint8, uint[] memory); } interface IContractDeposits { function createOrderBot(address _owner, address _token_in, uint _value_in, address _token_out, uint _value_out, uint _order_position) external returns (uint256); function getTypeAndPriceOrder(address _token_in, uint _value_in, address _token_out, uint _value_out) external view returns (uint8, uint256); function getTypeAndValue(address _token_in, address _token_out, uint _value, uint _price) external view returns (uint8, uint256); function getWrappedAndPricelimit() external view returns (address, uint256, uint256); function payTheOracle(address _owner, address _oracle, uint _gasUsed) external returns (uint256); } interface IContractOrders { function cancelOrders(uint[] memory _id_arr) external returns (uint [] memory); function deleteCloseOrders(uint[] memory _id_arr) external returns (uint [] memory); function getLockedTokensForOracle(uint _id1, uint _id2) external view returns (uint [] memory); function getOrderDataForOracle(uint _id) external view returns (uint [] memory); } interface IERC20 { function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); } contract TwoBearsBots { struct ListID{ uint256 time; // время создания бота / время частичного исполнения ордера uint256 next; // указатель на следующий id uint256 prev; // указатель на предыдущий id } struct BotID{ uint256 id_sell; // ID ордера продажи // ID ордера uint256 id_buy; // ID ордера покупки // 0 uint256 value_sell; // количество продажи // Количество uint256 value_buy; // количество покупки // Увеличение количества uint256 price; // цена исполнения // Цена uint256 price_step; // ценовой шаг (изменение цены после каждого успешно выполненого ордера). Зависит от типа ордера // Ценовой шаг uint256 price_up_limit; // верхний предел цены при котором бот прекращает работу // Предел цены uint256 price_down_limit; // нижний предел цены при котором бот прекращает работу // 0 uint256 paid_for_gas; // было заплачено за газ в нативной монете uint256 gave_1; // было отдано первого токена // отдано uint256 received_2; // было получено второго токена // получено uint256 commission_2; // биржевая комиссия во втором токене // комиссия uint256 gave_2; // было отдано второго токена // 0 uint256 received_1; // было получено первого токена // 0 uint256 commission_1; // биржевая комиссия в первом токене // 0 address token_in; // токен который отдает владелец // токена который отдает владелец address token_out; // токен который получает владелец // токена который получает владелец address owner; // владелец бота // владелец бота address oracle; // оракул что зафиксировал ошибку бота. Владелец бота должен оплатить работу оракула при снятии блокировки uint8 bot_type; // тип бота. 1 - распродажа, 2 - закупка, 3 - сеточная торговля // тип бота uint8 bot_status; // статус бота. 100 - Активен // статус бота } struct DataOracle{ // структура возврата данных для оракула, по запрошенному ордеру uint256 price_1; // первая цена для которой должен быть осуществен поиск позиции uint256 price_2; // вторая цена для которой должен быть осуществен поиск позиции address token_in_1; // Адрес первого входящего токена address token_out_1; // Адрес первого выходящего токена address token_in_2; // Адрес второго входящего токена address token_out_2; // Адрес второго выходящего токена uint8 bot_status; // статус бота. 100 - Активен. При других статусах оракул должен игнорировать ордера данного бота, пока владелец бота не устранит неисправность и не изменит статус на 100 } uint256 public id; // уникальный идентификатор бота mapping(uint256 => uint256) private ids; // id_ордера => id_бота mapping(address => mapping(uint256 => ListID)) private bots; // список всех ботов по владельцам mapping(uint256 => BotID) private id_bots; // все созданные схемы ботов mapping(address => bool) private oracles; // доверенные оракулы address public owner = 0xeBE894814554c8382EA6a24CcDdf1527407A24f6; // Владелец address public constant contractDeposits = 0x01C81c93f38F42497b4ceBfA23eeb03f7ccFA8C7; // Контракт с депозитами address public constant contractOrders = 0x11d5DB9473A6E017Ba4D182987bC5aB198C04A15; // Контракт с книгами ордеров address public constant contractBotsHelp = 0x6F8A583c11615C7CF713A76e79131FDF8761C3fE; // Вспомогательный контракт ботов event CreateBot(uint indexed ID); event DeleteBot(uint indexed ID); event AddOracle(address indexed oracle); event DeleteOracle(address indexed oracle); modifier onlyOwner() { require(msg.sender == owner, "Only owner can call this"); _; } modifier onlyOracle() { require(oracles[msg.sender] == true, "Only oracle can call this"); _; } // Обработаем функции получения нативной монеты и любых токенов ERC223 receive() external payable {} // принимаем нативную монету function tokenReceived(address _from, uint _value, bytes memory _data) public returns (bytes4) { // принимаем токены ERC223 return this.tokenReceived.selector; // возвращаем селектор этой функции } // Работа с ботами function createBotSellBuy(address _token_in, address _token_out, uint _value, uint _value_inc, uint _price, uint _price_step, uint _price_limit, uint _order_position) external { // создание бота распродажи / закупа // _value - объем токена с наименьшим приоритетом // _price - цена в токене с максимальным приоритетом BotID memory _bot; _bot.value_sell = _value; // Количество _bot.value_buy = _value_inc; // Увеличение количества _bot.price = _price; // Цена _bot.price_step = _price_step; // Ценовой шаг _bot.price_up_limit = _price_limit; // Предел цены _bot.token_in = _token_in; // токен который отдает владелец _bot.token_out = _token_out; // токен который получает владелец _bot.owner = msg.sender; // владелец бота uint256 _value_in; uint256 _value_out; (_bot.bot_status, _bot.bot_type, _value_in, _value_out) = IContractBotsHelp(contractBotsHelp).checkCreateBotSellBuy(msg.sender, _token_in, _token_out, _value, _value_inc, _price, _price_step, _price_limit); require(_bot.bot_status == 100); // Проверка создания бота должна быть успешна // Создаем торгового бота с выставлением первого ордера _bot.id_sell = createOrderBot(msg.sender, _token_in, _value_in, _token_out, _value_out, _order_position); ++id; // новый ID для создаваемого бота uint _id = id; id_bots[_id] = _bot; // сохраняем схему бота ids[_bot.id_sell] = _id; // привязываем открытый ордер к боту add_ID_bot(msg.sender, _id); // добавление нового бота в список владельца emit CreateBot(_id); } function createBotNetTrade(address _token_in, address _token_out, uint _value_sell, uint _value_buy, uint _price, uint _price_step, uint _price_up_limit, uint _price_down_limit, uint _order_position_sell, uint _order_position_buy) external { // создание бота сеточной торговли // _value_sell и _value_buy - объем токена с наименьшим приоритетом // _price - цена в токене с максимальным приоритетом // _token_in - будет установлен токен с минимальным приоритетом (сперва идет ордер продажи, а затем ордер покупки) BotID memory _bot; uint[] memory _values = new uint[](2); // получаем токена с макс. приоритером при продаже, отдаем токен с макс. приоритером при покупке (_bot.bot_status, _values[0], _values[1]) = IContractBotsHelp(contractBotsHelp).checkCreateBotNetTrade(msg.sender, _token_in, _token_out, _value_sell, _value_buy, _price, _price_step, _price_up_limit, _price_down_limit); if(_bot.bot_status == 101){ // проверка создания бота - успешна, но входящий и выходящий токена нужно поменять местами, так как сперва мы будем создавать ордер продажи, а затем ордер покупки (_token_in, _token_out) = (_token_out, _token_in); // входящий и выходящий токены меняем местами _bot.bot_status = 100; } require(_bot.bot_status == 100); // Проверка создания бота должна быть успешна // Заполняем схему бота _bot.value_sell = _value_sell; // количество продажи _bot.value_buy = _value_buy; // количество покупки _bot.price = _price; // промежуточная цена (между ордером исполнения и ордером продажи) _bot.price_step = _price_step; // ценовой шаг _bot.price_up_limit = _price_up_limit; // верхний предел цены при котором бот прекращает работу _bot.price_down_limit = _price_down_limit; // нижний предел цены при котором бот прекращает работу _bot.token_in = _token_in; // токен который отдает владелец _bot.token_out = _token_out; // токен который получает владелец _bot.owner = msg.sender; // владелец бота _bot.bot_type = 3; // тип бота. 3 - сеточная торговля // Создаем торгового бота с выставлением ордеров ++id; // новый ID для создаваемого бота uint _id = id; if(_values[0] > 0){ // необходимо создать ордер продажи _bot.id_sell = createOrderBot(msg.sender, _bot.token_in, _value_sell, _bot.token_out, _values[0], _order_position_sell); ids[_bot.id_sell] = _id; // привязываем открытый ордер продажи к боту } if(_values[1] > 0){ // необходимо создать ордер покупки _bot.id_buy = createOrderBot(msg.sender, _bot.token_out, _values[1], _bot.token_in, _value_buy, _order_position_buy); ids[_bot.id_buy] = _id; // привязываем открытый ордер покупки к боту } id_bots[_id] = _bot; // сохраняем схему бота add_ID_bot(msg.sender, _id); // добавление нового бота в список владельца emit CreateBot(_id); } // Вспомогательные функции ======================================== function createOrderBot(address _owner, address _token_in, uint _value_in, address _token_out, uint _value_out, uint _order_position) private returns (uint256){ // создание ордера от имени бота uint _id_ord = IContractDeposits(contractDeposits).createOrderBot(_owner, _token_in, _value_in, _token_out, _value_out, _order_position); return _id_ord; } function getTypeAndValue(address _token_in, address _token_out, uint _value, uint _price) private view returns (uint256) // вернуть объем токена с наивысшим приоритетом { uint256 _value_max_priority; (, _value_max_priority) = IContractDeposits(contractDeposits).getTypeAndValue(_token_in, _token_out, _value, _price); return (_value_max_priority); } function getTypeAndPriceOrder(address _token_in, uint _value_in, address _token_out, uint _value_out) private view returns (uint256) // вернуть цену ордера { uint256 _price; (, _price) = IContractDeposits(contractDeposits).getTypeAndPriceOrder(_token_in, _value_in, _token_out, _value_out); return (_price); } function payTheOracle(uint _id_bot, address _owner, address _oracle, uint _gasUsed) private { // оплатить работу оракула uint _value = IContractDeposits(contractDeposits).payTheOracle(_owner, _oracle, _gasUsed); // возвращаем сколько по факту получил оракул id_bots[_id_bot].paid_for_gas += _value; // обновляем статистику бота по газовым затратам } function transfer(address _token, address _recipient, uint _value) private { // перевод токена с баланса этого контракта uint256 _size; assembly { _size := extcodesize(_recipient) } // проверяем является ли адрес получателя контрактом if(_size > 0){ // если получатель это контракт IERC20(_token).approve(address(this), _value); //Даем разрешение нашему контракту тратить токен на своем балансе через TransferFrom IERC20(_token).transferFrom(address(this), _recipient, _value); } else{ // получатель это пользователь (EOA) IERC20(_token).transfer(_recipient, _value); } } // ================================================================= function add_ID_bot(address _owner, uint _id_bot) private { // добавление нового бота в список владельца uint _id_last = bots[_owner][0].prev; // получаем последнего созданного бота владельца bots[_owner][_id_last].next = _id_bot; bots[_owner][0].prev = _id_bot; bots[_owner][_id_bot] = ListID(block.timestamp, 0, _id_last); } function del_ID_bot(address _owner, uint _id_bot) private { // удаление бота из списка владельца uint _id_next = bots[_owner][_id_bot].next; uint _id_prev = bots[_owner][_id_bot].prev; bots[_owner][_id_prev].next = _id_next; bots[_owner][_id_next].prev = _id_prev; delete bots[_owner][_id_bot]; } function getBotByID(uint _id_bot) public view returns (BotID memory) // Возвращаем бота по ID { return (id_bots[_id_bot]); } function getAllBotsOwner(address _owner, uint _id_bot, uint _amount) public view returns (uint [] memory) // Возвращаем указанное количество ботов пользователя, со следующего ордера от стартового ID { // если _id_bot = 0, тогда информация по ботам формируются с самого первого бота /* возвращаемый массив 3 - тип: возвращаемый массив 1,2 - тип: [ ID_бота, ID_бота, время_создания, время_создания, тип бота, тип бота, адрес_токена_1, адрес_токена_1, заблокированное_количество_1, заблокированное_количество_1, адрес_токена_2, адрес_токена_2, заблокированное_количество_2, заблокированное_количество_2, отдано_1_токена, отдано, получено_2_токена, получено, отдано_2_токена, 0, получено_1_токена, 0, адрес_отдаваемого_токена, адрес_отдаваемого_токена, адрес_получаемого_токена_2, адрес_получаемого_токена, статус_бота, статус_бота, ...] */ _id_bot = bots[_owner][_id_bot].next; if(_id_bot == 0) return (new uint[](1)); // если открытых ботов еще не существует, либо если это первый бот в списке, который уже был обработан, вернем [0] uint _index; uint[] memory result = new uint[](_amount * 14); // возвращаемый массив for(uint i; i < _amount; i++){ if(_id_bot == 0) break; result[_index++] = _id_bot; result[_index++] = bots[_owner][_id_bot].time; result[_index++] = id_bots[_id_bot].bot_type; uint[] memory _lock_tokens = IContractOrders(contractOrders).getLockedTokensForOracle(id_bots[_id_bot].id_sell, id_bots[_id_bot].id_buy); // [токен1, количество1, токен2, количество2] result[_index++] = _lock_tokens[0]; result[_index++] = _lock_tokens[1]; result[_index++] = _lock_tokens[2]; result[_index++] = _lock_tokens[3]; result[_index++] = id_bots[_id_bot].gave_1; result[_index++] = id_bots[_id_bot].received_2; result[_index++] = id_bots[_id_bot].gave_2; result[_index++] = id_bots[_id_bot].received_1; result[_index++] = uint256(uint160(id_bots[_id_bot].token_in)); result[_index++] = uint256(uint160(id_bots[_id_bot].token_out)); result[_index++] = id_bots[_id_bot].bot_status; _id_bot = bots[_owner][_id_bot].next; } return (result); } // Функция проверки ордера (для получения данных оракулом) function checkOrderByOracle(uint _id_order) public view returns (DataOracle memory) { // Возвращаем необходимые данные по боту для поиска ценовых позиций в книгах ордеров. DataOracle memory _data; uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера _data.bot_status = id_bots[_id_bot].bot_status; // Определяем текущий статус бота if(_data.bot_status != 100) return (_data); // если бот неактивен или не существует uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен // определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой) uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step; uint _value_max_priority; // объем токена с максимальным приоритетом _data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота _data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли (_data.token_in_2, _data.token_out_2) = (_data.token_out_1, _data.token_in_1); // Инвертируем токены (для покупки) if(_order_data[1] == 1){ // данный ордер - продажа // следующий ордер продажи _value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, id_bots[_id_bot].value_sell, _price_temp + id_bots[_id_bot].price_step); _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, id_bots[_id_bot].value_sell, _data.token_out_1, _value_max_priority); // следующий ордер покупки uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_buy); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[3] : id_bots[_id_bot].value_buy; // определяем объем покупки. Если ордер покупки был со статусом 1, 6 или 9, тогда на покупку идет оставщийся, недокупленный объем _value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, _val, _price_temp - id_bots[_id_bot].price_step); _data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, _val); } else{ // данный ордер - покупка // следующий ордер покупки _value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, id_bots[_id_bot].value_buy, _price_temp - id_bots[_id_bot].price_step); _data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, id_bots[_id_bot].value_buy); // следующий ордер продажи uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_sell); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[2] : id_bots[_id_bot].value_sell; // определяем объем продажи. Если ордер продажи был со статусом 1, 6 или 9, тогда на продажу идет оставщийся, непроданный объем _value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _val, _price_temp + id_bots[_id_bot].price_step); _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _val, _data.token_out_1, _value_max_priority); } } else{ // бот распродажи или закупа uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем) _value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _value, _price_temp); (_value, _value_max_priority) = (_order_data[1] == 1) ? (_value, _value_max_priority) : (_value_max_priority, _value); _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _value, _data.token_out_1, _value_max_priority); } } else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров) if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота _data.token_in_1 = id_bots[_id_bot].token_in; _data.token_out_1 = id_bots[_id_bot].token_out; } else{ // это покупка у сеточного бота _data.token_in_1 = id_bots[_id_bot].token_out; _data.token_out_1 = id_bots[_id_bot].token_in; } _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _order_data[2], _data.token_out_1, _order_data[3]); } return (_data); } function workBot(uint _id_order, uint _order_position_1, uint _order_position_2) external onlyOracle { // основная функция оракула (двигатель ботов) uint _gasUsed = gasleft(); // начинаем расчет газа для оракула uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера require(id_bots[_id_bot].bot_status == 100); // статус бота должен быть 100 - активен address _owner = id_bots[_id_bot].owner; // Владелец бота uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен // определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой) uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step; DataOracle memory _data; _data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота _data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли // _data.price_2 - ID второго ордера из схемы ботов _data.price_2 = (id_bots[_id_bot].id_sell == _id_order) ? id_bots[_id_bot].id_buy : id_bots[_id_bot].id_sell; // получим данные второго ордера uint[] memory _order_data_2 = IContractOrders(contractOrders).getOrderDataForOracle(_data.price_2); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки uint[] memory _param = new uint[](6); // [количество_продажи, количество_покупки, цена, шаг, верхний_предел_цены, нижний_предел_цены] _param[0] = id_bots[_id_bot].value_sell; _param[1] = id_bots[_id_bot].value_buy; _param[2] = _price_temp; _param[3] = id_bots[_id_bot].price_step; _param[4] = id_bots[_id_bot].price_up_limit; _param[5] = id_bots[_id_bot].price_down_limit; (_data.bot_status, _result) = IContractBotsHelp(contractBotsHelp).checkSchemeBotNetTrade(_owner, _data.token_in_1, _data.token_out_1, _param, _order_data, _order_data_2); if(_data.bot_status > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете id_bots[_id_bot].oracle = msg.sender; // оракул id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки return; } // Удаляем ордера и отвязываем их от ботов deleteOrder(_id_order, _order_data); // удаляем ордер со статусом 7 if(_data.price_2 > 0){ // если второй ордер существует deleteOrder(_data.price_2, _order_data_2); // удаляем второй ордер с отвязкой его от бота } id_bots[_id_bot].price = _price_temp; // текущая цена // Создаем новые ордера согласно схеме бота //uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки if(_result[0] > 0){ // нужно создавать ордер продажи uint _ord = _order_position_1; // позиция ордера продажи _ord = createOrderBot(_owner, _data.token_in_1, _result[0], _data.token_out_1, _result[1], _ord); ids[_ord] = _id_bot; // привязываем открытый ордер продажи к боту id_bots[_id_bot].id_sell = _ord; } else{ // ордер продажи создавать не нужно, он вышел за верхний предел id_bots[_id_bot].id_sell = 0; } if(_result[2] > 0){ // нужно создавать ордер покупки uint _ord = _order_position_2; // позиция ордера покупки _ord = createOrderBot(_owner, _data.token_out_1, _result[2], _data.token_in_1, _result[3], _ord); ids[_ord] = _id_bot; // привязываем открытый ордер покупки к боту id_bots[_id_bot].id_buy = _ord; } else{ // ордер продажи создавать не нужно, он вышел за верхний предел id_bots[_id_bot].id_buy = 0; } } else{ // бот распродажи или закупа // _data.price_1 - количество входящего токена. _data.price_2 - количество выходящего токена uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем) (_data.bot_status, _data.price_1, _data.price_2) = IContractBotsHelp(contractBotsHelp).checkSchemeBotSellBuy(_owner, _data.token_in_1, _data.token_out_1, _value, _price_temp, id_bots[_id_bot].price_up_limit); if(_data.bot_status == 100){ // нужно создавать новый ордер. Схема активна deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота id_bots[_id_bot].value_sell = _value; // текущее количество токена id_bots[_id_bot].price = _price_temp; // текущая цена // создадим новый ордер схемы. _value - ID ордера _value = createOrderBot(_owner, _data.token_in_1, _data.price_1, _data.token_out_1, _data.price_2, _order_position_1); ids[_value] = _id_bot; // привязываем открытый ордер продажи к боту id_bots[_id_bot].id_sell = _value; } else if (_data.bot_status == 200) { // Схема бота полностью отработала deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота id_bots[_id_bot].id_sell = 0; id_bots[_id_bot].bot_status = 200; // статус бота 200 - бот полностью завершил схему } else{ // возникла ошибка в работе схемы бота id_bots[_id_bot].oracle = msg.sender; // оракул id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки return; } } } else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров) uint8 _err; // Для возврата кода ошибки; (address _token_in, address _token_out) = (id_bots[_id_bot].id_sell == _id_order) ? (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out) : (id_bots[_id_bot].token_out, id_bots[_id_bot].token_in); // входящий токен обрабатываемого ордера _err = IContractBotsHelp(contractBotsHelp).checkApproveAndBalance(_owner, _token_in, _order_data[2], _order_data[2]); if(_err > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете id_bots[_id_bot].oracle = msg.sender; // оракул - создатель транзакции id_bots[_id_bot].bot_status = _err; // статус бота принимает код ошибки return; } deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота uint _new_order = createOrderBot(_owner, _token_in, _order_data[2], _token_out, _order_data[3], _order_position_1); ids[_new_order] = _id_bot; // привязываем открытый ордер продажи к боту if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота id_bots[_id_bot].id_sell = _new_order; } else{ // это покупка у сеточного бота id_bots[_id_bot].id_buy = _new_order; } } else{ // оракул пытается обработать ордер без статуса 7 или 9. Газ такому оракулу не компенсируем return; } // Оплачиваем работу оракула payTheOracle(_id_bot, _owner, msg.sender, _gasUsed - gasleft()); // оплата работы оракула } function deleteOrder(uint _id_order, uint[] memory _order_data) private { // выплачиваем все по ордеру, обновляем статистику бота, удаляем ордер и отвязываем его от бота // _order_data - массив данных по ордеру [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера address _owner = id_bots[_id_bot].owner; // Владелец бота address _token_in; // входящий токен ордера address _token_out; // выходящий токен ордера if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота (_token_in, _token_out) = (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out); if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен) id_bots[_id_bot].gave_1 += _order_data[4]; // отдал при обмене - первого токена id_bots[_id_bot].received_2 += _order_data[5]; // получил при обмене - второго токена if(_order_data[6] > 0) id_bots[_id_bot].commission_2 += _order_data[6]; // биржевая комиссия за исполнение ордера во втором токене } } else{ // это покупка у сеточного бота (_token_in, _token_out) = (id_bots[_id_bot].token_out, id_bots[_id_bot].token_in); if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен) id_bots[_id_bot].gave_2 += _order_data[4]; // отдал при обмене - второго токена id_bots[_id_bot].received_1 += _order_data[5]; // получил при обмене - первого токена if(_order_data[6] > 0) id_bots[_id_bot].commission_1 += _order_data[6]; // биржевая комиссия за исполнение ордера в первом токене } } // статистика бота обновлена. Делаем возвраты токенов владельцу if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен), то был получен второй токен transfer(_token_out, _owner, _order_data[5]); // выплачиваем владельцу бота то что было получено при обмене } uint[] memory _arr = new uint[](1); // создаем массив из 1 элемента if(_order_data[2] > 0){ // если есть необмененый остаток, то отменяем ордер и выплачиваем его _arr[0] = _id_order; // записываем в него ID ордера IContractOrders(contractOrders).cancelOrders(_arr); // отменяем ордер для возврата средств на адрес этого контракта transfer(_token_in, _owner, _order_data[2]); // выплачиваем владельцу бота то что не было обменяно } // удаляем отработанный / отмененый ордер. Данный ордер должен быть убран из книги закрытых ордеров _arr[0] = _id_order; // записываем в массив ID ордера IContractOrders(contractOrders).deleteCloseOrders(_arr); delete ids[_id_order]; // разрушаем связь между ордером и ботом } function restoreBot(uint _id_bot) external // Восстановление бота. Когда пользователь устранит неисправность бота, он должен вызвать эту функцию чтобы вернуть боту статус 100 { uint8 _stat = id_bots[_id_bot].bot_status; // получим статус бота require(_stat > 0); // бот должен существовать require((_stat != 100) && (_stat != 200)); // Статус бота не должен быть 100 - активен и 200 - бот завершил схему require(msg.sender == id_bots[_id_bot].owner); // только владелец бота может разблокировать бота payTheOracle(_id_bot, msg.sender, id_bots[_id_bot].oracle, 0); // оплачиваем газ оракула за обнаружение неисправности бота id_bots[_id_bot].bot_status = 100; // возобновляем работу бота } function deleteBot(uint _id_bot) external // Удаление бота { // перед удалением бота автоматически закрываются все ордера и все токены возвращаются владельцу require(bots[msg.sender][_id_bot].time > 0); // удаляемый бот должен принадлежать владельцу uint8 _status = id_bots[_id_bot].bot_status; // получим статус бота if((_status != 100) && (_status != 200)){ // бот находится в состоянии ошибки payTheOracle(_id_bot, msg.sender, id_bots[_id_bot].oracle, 0); // оплачиваем газ оракула за обнаружение неисправности бота } if(_status != 200){ // текущая схема активна, либо бот в состоянии ошибки uint _id_sell = id_bots[_id_bot].id_sell; uint _id_buy = id_bots[_id_bot].id_buy; if(_id_sell > 0){ // Нужно удалять ордер uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_sell); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] deleteOrder(_id_sell, _order_data); // удаляем ордер с отвязкой его от бота } if(_id_buy > 0){ // Нужно удалять ордер uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_buy); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] deleteOrder(_id_buy, _order_data); // удаляем ордер с отвязкой его от бота } } del_ID_bot(msg.sender, _id_bot); // удаление бота из списка владельца delete id_bots[_id_bot]; // удаление схемы бота emit DeleteBot(_id_bot); } // ФУНКЦИИ ВЛАДЕЛЬЦА function addOracle(address _oracle) external onlyOwner // добавить доверенного оракула { oracles[_oracle] = true; emit AddOracle(_oracle); } function deleteOracle(address _oracle) external onlyOwner // удалить доверенного оракула { oracles[_oracle] = false; emit DeleteOracle(_oracle); } function isOracle(address _oracle) public view returns (bool) // проверяем является ли адрес оракулом { return (oracles[_oracle]); } }
Contract ABI
[{"type":"event","name":"AddOracle","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"CreateBot","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"DeleteBot","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"DeleteOracle","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TwoBearsBots.DataOracle","components":[{"type":"uint256","name":"price_1","internalType":"uint256"},{"type":"uint256","name":"price_2","internalType":"uint256"},{"type":"address","name":"token_in_1","internalType":"address"},{"type":"address","name":"token_out_1","internalType":"address"},{"type":"address","name":"token_in_2","internalType":"address"},{"type":"address","name":"token_out_2","internalType":"address"},{"type":"uint8","name":"bot_status","internalType":"uint8"}]}],"name":"checkOrderByOracle","inputs":[{"type":"uint256","name":"_id_order","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractBotsHelp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractDeposits","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractOrders","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createBotNetTrade","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_value_sell","internalType":"uint256"},{"type":"uint256","name":"_value_buy","internalType":"uint256"},{"type":"uint256","name":"_price","internalType":"uint256"},{"type":"uint256","name":"_price_step","internalType":"uint256"},{"type":"uint256","name":"_price_up_limit","internalType":"uint256"},{"type":"uint256","name":"_price_down_limit","internalType":"uint256"},{"type":"uint256","name":"_order_position_sell","internalType":"uint256"},{"type":"uint256","name":"_order_position_buy","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createBotSellBuy","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"uint256","name":"_value_inc","internalType":"uint256"},{"type":"uint256","name":"_price","internalType":"uint256"},{"type":"uint256","name":"_price_step","internalType":"uint256"},{"type":"uint256","name":"_price_limit","internalType":"uint256"},{"type":"uint256","name":"_order_position","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteBot","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getAllBotsOwner","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id_bot","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TwoBearsBots.BotID","components":[{"type":"uint256","name":"id_sell","internalType":"uint256"},{"type":"uint256","name":"id_buy","internalType":"uint256"},{"type":"uint256","name":"value_sell","internalType":"uint256"},{"type":"uint256","name":"value_buy","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"price_step","internalType":"uint256"},{"type":"uint256","name":"price_up_limit","internalType":"uint256"},{"type":"uint256","name":"price_down_limit","internalType":"uint256"},{"type":"uint256","name":"paid_for_gas","internalType":"uint256"},{"type":"uint256","name":"gave_1","internalType":"uint256"},{"type":"uint256","name":"received_2","internalType":"uint256"},{"type":"uint256","name":"commission_2","internalType":"uint256"},{"type":"uint256","name":"gave_2","internalType":"uint256"},{"type":"uint256","name":"received_1","internalType":"uint256"},{"type":"uint256","name":"commission_1","internalType":"uint256"},{"type":"address","name":"token_in","internalType":"address"},{"type":"address","name":"token_out","internalType":"address"},{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"oracle","internalType":"address"},{"type":"uint8","name":"bot_type","internalType":"uint8"},{"type":"uint8","name":"bot_status","internalType":"uint8"}]}],"name":"getBotByID","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"id","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"restoreBot","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"workBot","inputs":[{"type":"uint256","name":"_id_order","internalType":"uint256"},{"type":"uint256","name":"_order_position_1","internalType":"uint256"},{"type":"uint256","name":"_order_position_2","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50615cb180620000766000396000f3fe6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b6040516101309190614a65565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b9190614ac0565b61044d565b005b34801561016e57600080fd5b5061017761057b565b6040516101849190614a65565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af9190614b23565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614b76565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614c2c565b61198b565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614d0b565b611f81565b60405161023c9190614e1c565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614f84565b612640565b604051610279919061502e565b60405180910390f35b34801561028e57600080fd5b50610297612653565b6040516102a49190614a65565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf9190614ac0565b612679565b6040516102e19190615064565b60405180910390f35b3480156102f657600080fd5b506102ff6126cf565b60405161030c919061508e565b60405180910390f35b34801561032157600080fd5b5061033c600480360381019061033791906150a9565b6126d5565b005b34801561034a57600080fd5b50610365600480360381019061036091906150a9565b612ae7565b60405161037291906152b4565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d91906150a9565b612d3d565b6040516103af919061535e565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190614ac0565b613821565b005b3480156103ed57600080fd5b506103f661394f565b6040516104039190614a65565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e91906150a9565b613967565b005b736f8a583c11615c7cf713a76e79131fdf8761c3fe81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d4906153d6565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b7301c81c93f38f42497b4cebfa23eeb03f7ccfa8c781565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615442565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060120160159054906101000a900460ff1660ff161461067657600080fd5b60006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b8152600401610700919061508e565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610746919061553f565b905060078160008151811061075e5761075d615588565b5b60200260200101510361119557600060018260018151811061078357610782615588565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906155e6565b610806565b60036000858152602001908152602001600020600501546003600086815260200190815260200160002060040154610805919061561a565b5b905061081061488e565b60036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060120160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b81602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c6919061508e565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c919061553f565b905060606000600667ffffffffffffffff811115610a2d57610a2c614e59565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a88615588565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf615588565b5b6020026020010181815250508481600281518110610ae157610ae0615588565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b17615588565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e615588565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b85615588565b5b602002602001018181525050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf19695949392919061564e565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906156f0565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613aa5565b600084602001511115610d1657610d15846020015184613aa5565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d46615588565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d76615588565b5b6020026020010151886060015187600181518110610d9857610d97615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e13615588565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e43615588565b5b6020026020010151886040015187600381518110610e6557610e64615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d919061561a565b9050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f849695949392919061574c565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc591906157ad565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613aa5565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e6140c0565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613aa5565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa615588565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d576003600087815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b91509150736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663ad148af486848760028151811061130657611305615588565b5b60200260200101518860028151811061132257611321615588565b5b60200260200101516040518563ffffffff1660e01b81526004016113499493929190615800565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a9190615845565b925060008360ff16111561142857336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613aa5565b600061147886848760028151811061144d5761144c615588565b5b6020026020010151858960038151811061146a57611469615588565b5b60200260200101518f6140c0565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906155e6565b61416d565b505050505b505050565b611527614926565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508781610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503381610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600080736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b8152600401611662989796959493929190615872565b608060405180830381865afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a391906158f0565b866102800187610260018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610280015160ff16146116e057600080fd5b6116ee338c848d85896140c0565b836000018181525050600080815461170590615957565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119503382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b611993614926565b6000600267ffffffffffffffff8111156119b0576119af614e59565b5b6040519080825280602002602001820160405280156119de5781602001602082028036833780820191505090505b509050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611a3e9998979695949392919061599f565b606060405180830381865afa158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f91906157ad565b846102800184600081518110611a9857611a97615588565b5b6020026020010185600181518110611ab357611ab2615588565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610280015160ff1603611afe578a8c809c50819d505050606482610280019060ff16908160ff16815250505b606482610280015160ff1614611b1357600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a82610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503382610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610260019060ff16908160ff16815250506000808154611c1c90615957565b91905081905550600080549050600082600081518110611c3f57611c3e615588565b5b60200260200101511115611ca657611c8033846101e001518d86610200015186600081518110611c7257611c71615588565b5b60200260200101518a6140c0565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611cbc57611cbb615588565b5b60200260200101511115611d2357611cfd3384610200015184600181518110611ce857611ce7615588565b5b6020026020010151866101e001518e896140c0565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050611f453382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001015492506000830361203257600167ffffffffffffffff811115611ffc57611ffb614e59565b5b60405190808252806020026020018201604052801561202a5781602001602082028036833780820191505090505b509050612639565b600080600e846120429190615a2c565b67ffffffffffffffff81111561205b5761205a614e59565b5b6040519080825280602002602001820160405280156120895781602001602082028036833780820191505090505b50905060005b8481101561263257600086031561263257858284806120ad90615957565b9550815181106120c0576120bf615588565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000015482848061212c90615957565b95508151811061213f5761213e615588565b5b6020026020010181815250506003600087815260200190815260200160002060120160149054906101000a900460ff1660ff1682848061217e90615957565b95508151811061219157612190615588565b5b60200260200101818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b815260040161221a929190615a86565b600060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612260919061553f565b90508060008151811061227657612275615588565b5b602002602001015183858061228a90615957565b96508151811061229d5761229c615588565b5b602002602001018181525050806001815181106122bd576122bc615588565b5b60200260200101518385806122d190615957565b9650815181106122e4576122e3615588565b5b6020026020010181815250508060028151811061230457612303615588565b5b602002602001015183858061231890615957565b96508151811061232b5761232a615588565b5b6020026020010181815250508060038151811061234b5761234a615588565b5b602002602001015183858061235f90615957565b96508151811061237257612371615588565b5b60200260200101818152505060036000888152602001908152602001600020600901548385806123a190615957565b9650815181106123b4576123b3615588565b5b60200260200101818152505060036000888152602001908152602001600020600a01548385806123e390615957565b9650815181106123f6576123f5615588565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061242590615957565b96508151811061243857612437615588565b5b60200260200101818152505060036000888152602001908152602001600020600d015483858061246790615957565b96508151811061247a57612479615588565b5b60200260200101818152505060036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168385806124df90615957565b9650815181106124f2576124f1615588565b5b6020026020010181815250506003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061255790615957565b96508151811061256a57612569615588565b5b6020026020010181815250506003600088815260200190815260200160002060120160159054906101000a900460ff1660ff168385806125a990615957565b9650815181106125bc576125bb615588565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088815260200190815260200160002060010154965050808061262a90615957565b91505061208f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161273557600080fd5b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060648160ff1614158015612775575060c88160ff1614155b156127be576127bd82336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b5b60c88160ff161461295a5760006003600084815260200190815260200160002060000154905060006003600085815260200190815260200160002060010154905060008211156128ab5760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b8152600401612857919061508e565b600060405180830381865afa158015612874573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061289d919061553f565b90506128a98382613aa5565b505b60008111156129575760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b8152600401612903919061508e565b600060405180830381865afa158015612920573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612949919061553f565b90506129558282613aa5565b505b50505b61296433836143d3565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160009055600e820160009055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160146101000a81549060ff02191690556012820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612aef614926565b60036000838152602001908152602001600020604051806102a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016011820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160149054906101000a900460ff1660ff1660ff1681526020016012820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612d4561488e565b612d4d61488e565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060120160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612db357819250505061381c565b60007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e02919061508e565b600060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e48919061553f565b9050600781600081518110612e6057612e5f615588565b5b6020026020010151036135c2576000600182600181518110612e8557612e84615588565b5b602002602001015114612ecf5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612eca91906155e6565b612f08565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f07919061561a565b5b9050600060036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060120160149054906101000a900460ff1660ff16036135155784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061309f5761309e615588565b5b6020026020010151036132e0576130f78560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866130f2919061561a565b6145a4565b90506131238560400151600360008781526020019081526020016000206002015487606001518461464c565b85600001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b8152600401613191919061508e565b600060405180830381865afa1580156131ae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906131d7919061553f565b905060006001826000815181106131f1576131f0615588565b5b60200260200101511480613220575060068260008151811061321657613215615588565b5b6020026020010151145b80613246575060098260008151811061323c5761323b615588565b5b6020026020010151145b613266576003600087815260200190815260200160002060030154613283565b8160038151811061327a57613279615588565b5b60200260200101515b90506132ba87608001518860a0015183600360008b815260200190815260200160002060050154886132b591906155e6565b6145a4565b92506132d08760800151848960a001518461464c565b8760200181815250505050613510565b61332b85608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661332691906155e6565b6145a4565b90506133578560800151828760a00151600360008981526020019081526020016000206003015461464c565b85602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016133c5919061508e565b600060405180830381865afa1580156133e2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061340b919061553f565b9050600060018260008151811061342557613424615588565b5b60200260200101511480613454575060068260008151811061344a57613449615588565b5b6020026020010151145b8061347a57506009826000815181106134705761346f615588565b5b6020026020010151145b61349a5760036000878152602001908152602001600020600201546134b7565b816002815181106134ae576134ad615588565b5b60200260200101515b90506134ee8760400151886060015183600360008b815260200190815260200160002060050154886134e9919061561a565b6145a4565b925061350487604001518289606001518661464c565b87600001818152505050505b6135bb565b60006003600086815260200190815260200160002060030154600360008781526020019081526020016000206002015461354f919061561a565b90506135658660400151876060015183866145a4565b915060018460018151811061357d5761357c615588565b5b602002602001015114613591578181613594565b80825b80935081925050506135b086604001518288606001518561464c565b866000018181525050505b5050613815565b6009816000815181106135d8576135d7615588565b5b60200260200101510361381457846003600084815260200190815260200160002060000154036136e35760036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506137c0565b6003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b61380a8360400151826002815181106137dc576137db615588565b5b60200260200101518560600151846003815181106137fd576137fc615588565b5b602002602001015161464c565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146138b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138a8906153d6565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b7311d5db9473a6e017ba4d182987bc5ab198c04a1581565b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060008160ff161161399f57600080fd5b60648160ff16141580156139b7575060c88160ff1614155b6139c057600080fd5b6003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613a2e57600080fd5b613a7182336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b60646003600084815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050565b60006001600084815260200190815260200160002054905060006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613cb55760036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613ba457613ba3615588565b5b60200260200101511115613cb05784600481518110613bc657613bc5615588565b5b6020026020010151600360008681526020019081526020016000206009016000828254613bf3919061561a565b9250508190555084600581518110613c0e57613c0d615588565b5b602002602001015160036000868152602001908152602001600020600a016000828254613c3b919061561a565b92505081905550600085600681518110613c5857613c57615588565b5b60200260200101511115613caf5784600681518110613c7a57613c79615588565b5b602002602001015160036000868152602001908152602001600020600b016000828254613ca7919061561a565b925050819055505b5b613e4e565b6003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d4157613d40615588565b5b60200260200101511115613e4d5784600481518110613d6357613d62615588565b5b602002602001015160036000868152602001908152602001600020600c016000828254613d90919061561a565b9250508190555084600581518110613dab57613daa615588565b5b602002602001015160036000868152602001908152602001600020600d016000828254613dd8919061561a565b92505081905550600085600681518110613df557613df4615588565b5b60200260200101511115613e4c5784600681518110613e1757613e16615588565b5b602002602001015160036000868152602001908152602001600020600e016000828254613e44919061561a565b925050819055505b5b5b600085600581518110613e6457613e63615588565b5b60200260200101511115613e9957613e98818487600581518110613e8b57613e8a615588565b5b60200260200101516146f4565b5b6000600167ffffffffffffffff811115613eb657613eb5614e59565b5b604051908082528060200260200182016040528015613ee45781602001602082028036833780820191505090505b509050600086600281518110613efd57613efc615588565b5b60200260200101511115613fe9578681600081518110613f2057613f1f615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613f799190614e1c565b6000604051808303816000875af1158015613f98573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613fc1919061553f565b50613fe8838588600281518110613fdb57613fda615588565b5b60200260200101516146f4565b5b8681600081518110613ffe57613ffd615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016140579190614e1c565b6000604051808303816000875af1158015614076573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061409f919061553f565b50600160008881526020019081526020016000206000905550505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b815260040161411a96959493929190615aaf565b6020604051808303816000875af1158015614139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415d9190615b10565b9050809150509695505050505050565b60007301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b81526004016141c093929190615b3d565b6020604051808303816000875af11580156141df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142039190615b10565b90508060036000878152602001908152602001600020600801600082825461422b919061561a565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016145fa9493929190615800565b6040805180830381865afa158015614616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463a9190615b74565b90508091505080915050949350505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016146a29493929190615bb4565b6040805180830381865afa1580156146be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146e29190615b74565b90508091505080915050949350505050565b6000823b90506000811115614808578373ffffffffffffffffffffffffffffffffffffffff1663095ea7b330846040518363ffffffff1660e01b815260040161473e929190615bf9565b6020604051808303816000875af115801561475d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147819190615c4e565b508373ffffffffffffffffffffffffffffffffffffffff166323b872dd3085856040518463ffffffff1660e01b81526004016147bf93929190615b3d565b6020604051808303816000875af11580156147de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148029190615c4e565b50614888565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401614843929190615bf9565b6020604051808303816000875af1158015614862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148869190615c4e565b505b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b604051806102a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614a4f82614a24565b9050919050565b614a5f81614a44565b82525050565b6000602082019050614a7a6000830184614a56565b92915050565b6000604051905090565b600080fd5b600080fd5b614a9d81614a44565b8114614aa857600080fd5b50565b600081359050614aba81614a94565b92915050565b600060208284031215614ad657614ad5614a8a565b5b6000614ae484828501614aab565b91505092915050565b6000819050919050565b614b0081614aed565b8114614b0b57600080fd5b50565b600081359050614b1d81614af7565b92915050565b600080600060608486031215614b3c57614b3b614a8a565b5b6000614b4a86828701614b0e565b9350506020614b5b86828701614b0e565b9250506040614b6c86828701614b0e565b9150509250925092565b600080600080600080600080610100898b031215614b9757614b96614a8a565b5b6000614ba58b828c01614aab565b9850506020614bb68b828c01614aab565b9750506040614bc78b828c01614b0e565b9650506060614bd88b828c01614b0e565b9550506080614be98b828c01614b0e565b94505060a0614bfa8b828c01614b0e565b93505060c0614c0b8b828c01614b0e565b92505060e0614c1c8b828c01614b0e565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614c5057614c4f614a8a565b5b6000614c5e8d828e01614aab565b9a50506020614c6f8d828e01614aab565b9950506040614c808d828e01614b0e565b9850506060614c918d828e01614b0e565b9750506080614ca28d828e01614b0e565b96505060a0614cb38d828e01614b0e565b95505060c0614cc48d828e01614b0e565b94505060e0614cd58d828e01614b0e565b935050610100614ce78d828e01614b0e565b925050610120614cf98d828e01614b0e565b9150509295989b9194979a5092959850565b600080600060608486031215614d2457614d23614a8a565b5b6000614d3286828701614aab565b9350506020614d4386828701614b0e565b9250506040614d5486828701614b0e565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d9381614aed565b82525050565b6000614da58383614d8a565b60208301905092915050565b6000602082019050919050565b6000614dc982614d5e565b614dd38185614d69565b9350614dde83614d7a565b8060005b83811015614e0f578151614df68882614d99565b9750614e0183614db1565b925050600181019050614de2565b5085935050505092915050565b60006020820190508181036000830152614e368184614dbe565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614e9182614e48565b810181811067ffffffffffffffff82111715614eb057614eaf614e59565b5b80604052505050565b6000614ec3614a80565b9050614ecf8282614e88565b919050565b600067ffffffffffffffff821115614eef57614eee614e59565b5b614ef882614e48565b9050602081019050919050565b82818337600083830152505050565b6000614f27614f2284614ed4565b614eb9565b905082815260208101848484011115614f4357614f42614e43565b5b614f4e848285614f05565b509392505050565b600082601f830112614f6b57614f6a614e3e565b5b8135614f7b848260208601614f14565b91505092915050565b600080600060608486031215614f9d57614f9c614a8a565b5b6000614fab86828701614aab565b9350506020614fbc86828701614b0e565b925050604084013567ffffffffffffffff811115614fdd57614fdc614a8f565b5b614fe986828701614f56565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61502881614ff3565b82525050565b6000602082019050615043600083018461501f565b92915050565b60008115159050919050565b61505e81615049565b82525050565b60006020820190506150796000830184615055565b92915050565b61508881614aed565b82525050565b60006020820190506150a3600083018461507f565b92915050565b6000602082840312156150bf576150be614a8a565b5b60006150cd84828501614b0e565b91505092915050565b6150df81614a44565b82525050565b600060ff82169050919050565b6150fb816150e5565b82525050565b6102a0820160008201516151186000850182614d8a565b50602082015161512b6020850182614d8a565b50604082015161513e6040850182614d8a565b5060608201516151516060850182614d8a565b5060808201516151646080850182614d8a565b5060a082015161517760a0850182614d8a565b5060c082015161518a60c0850182614d8a565b5060e082015161519d60e0850182614d8a565b506101008201516151b2610100850182614d8a565b506101208201516151c7610120850182614d8a565b506101408201516151dc610140850182614d8a565b506101608201516151f1610160850182614d8a565b50610180820151615206610180850182614d8a565b506101a082015161521b6101a0850182614d8a565b506101c08201516152306101c0850182614d8a565b506101e08201516152456101e08501826150d6565b5061020082015161525a6102008501826150d6565b5061022082015161526f6102208501826150d6565b506102408201516152846102408501826150d6565b506102608201516152996102608501826150f2565b506102808201516152ae6102808501826150f2565b50505050565b60006102a0820190506152ca6000830184615101565b92915050565b60e0820160008201516152e66000850182614d8a565b5060208201516152f96020850182614d8a565b50604082015161530c60408501826150d6565b50606082015161531f60608501826150d6565b50608082015161533260808501826150d6565b5060a082015161534560a08501826150d6565b5060c082015161535860c08501826150f2565b50505050565b600060e08201905061537360008301846152d0565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006153c0601883615379565b91506153cb8261538a565b602082019050919050565b600060208201905081810360008301526153ef816153b3565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b600061542c601983615379565b9150615437826153f6565b602082019050919050565b6000602082019050818103600083015261545b8161541f565b9050919050565b600067ffffffffffffffff82111561547d5761547c614e59565b5b602082029050602081019050919050565b600080fd5b6000815190506154a281614af7565b92915050565b60006154bb6154b684615462565b614eb9565b905080838252602082019050602084028301858111156154de576154dd61548e565b5b835b8181101561550757806154f38882615493565b8452602084019350506020810190506154e0565b5050509392505050565b600082601f83011261552657615525614e3e565b5b81516155368482602086016154a8565b91505092915050565b60006020828403121561555557615554614a8a565b5b600082015167ffffffffffffffff81111561557357615572614a8f565b5b61557f84828501615511565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006155f182614aed565b91506155fc83614aed565b9250828203905081811115615614576156136155b7565b5b92915050565b600061562582614aed565b915061563083614aed565b9250828201905080821115615648576156476155b7565b5b92915050565b600060c0820190506156636000830189614a56565b6156706020830188614a56565b61567d6040830187614a56565b818103606083015261568f8186614dbe565b905081810360808301526156a38185614dbe565b905081810360a08301526156b78184614dbe565b9050979650505050505050565b6156cd816150e5565b81146156d857600080fd5b50565b6000815190506156ea816156c4565b92915050565b6000806040838503121561570757615706614a8a565b5b6000615715858286016156db565b925050602083015167ffffffffffffffff81111561573657615735614a8f565b5b61574285828601615511565b9150509250929050565b600060c0820190506157616000830189614a56565b61576e6020830188614a56565b61577b6040830187614a56565b615788606083018661507f565b615795608083018561507f565b6157a260a083018461507f565b979650505050505050565b6000806000606084860312156157c6576157c5614a8a565b5b60006157d4868287016156db565b93505060206157e586828701615493565b92505060406157f686828701615493565b9150509250925092565b60006080820190506158156000830187614a56565b6158226020830186614a56565b61582f604083018561507f565b61583c606083018461507f565b95945050505050565b60006020828403121561585b5761585a614a8a565b5b6000615869848285016156db565b91505092915050565b600061010082019050615888600083018b614a56565b615895602083018a614a56565b6158a26040830189614a56565b6158af606083018861507f565b6158bc608083018761507f565b6158c960a083018661507f565b6158d660c083018561507f565b6158e360e083018461507f565b9998505050505050505050565b6000806000806080858703121561590a57615909614a8a565b5b6000615918878288016156db565b9450506020615929878288016156db565b935050604061593a87828801615493565b925050606061594b87828801615493565b91505092959194509250565b600061596282614aed565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615994576159936155b7565b5b600182019050919050565b6000610120820190506159b5600083018c614a56565b6159c2602083018b614a56565b6159cf604083018a614a56565b6159dc606083018961507f565b6159e9608083018861507f565b6159f660a083018761507f565b615a0360c083018661507f565b615a1060e083018561507f565b615a1e61010083018461507f565b9a9950505050505050505050565b6000615a3782614aed565b9150615a4283614aed565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a7b57615a7a6155b7565b5b828202905092915050565b6000604082019050615a9b600083018561507f565b615aa8602083018461507f565b9392505050565b600060c082019050615ac46000830189614a56565b615ad16020830188614a56565b615ade604083018761507f565b615aeb6060830186614a56565b615af8608083018561507f565b615b0560a083018461507f565b979650505050505050565b600060208284031215615b2657615b25614a8a565b5b6000615b3484828501615493565b91505092915050565b6000606082019050615b526000830186614a56565b615b5f6020830185614a56565b615b6c604083018461507f565b949350505050565b60008060408385031215615b8b57615b8a614a8a565b5b6000615b99858286016156db565b9250506020615baa85828601615493565b9150509250929050565b6000608082019050615bc96000830187614a56565b615bd6602083018661507f565b615be36040830185614a56565b615bf0606083018461507f565b95945050505050565b6000604082019050615c0e6000830185614a56565b615c1b602083018461507f565b9392505050565b615c2b81615049565b8114615c3657600080fd5b50565b600081519050615c4881615c22565b92915050565b600060208284031215615c6457615c63614a8a565b5b6000615c7284828501615c39565b9150509291505056fea26469706673582212208bf560699041302fdf0ffe26c519debb442e5d35f90bd1e014428b716756e7f064736f6c63430008100033
Deployed ByteCode
0x6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b6040516101309190614a65565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b9190614ac0565b61044d565b005b34801561016e57600080fd5b5061017761057b565b6040516101849190614a65565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af9190614b23565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614b76565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614c2c565b61198b565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614d0b565b611f81565b60405161023c9190614e1c565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614f84565b612640565b604051610279919061502e565b60405180910390f35b34801561028e57600080fd5b50610297612653565b6040516102a49190614a65565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf9190614ac0565b612679565b6040516102e19190615064565b60405180910390f35b3480156102f657600080fd5b506102ff6126cf565b60405161030c919061508e565b60405180910390f35b34801561032157600080fd5b5061033c600480360381019061033791906150a9565b6126d5565b005b34801561034a57600080fd5b50610365600480360381019061036091906150a9565b612ae7565b60405161037291906152b4565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d91906150a9565b612d3d565b6040516103af919061535e565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190614ac0565b613821565b005b3480156103ed57600080fd5b506103f661394f565b6040516104039190614a65565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e91906150a9565b613967565b005b736f8a583c11615c7cf713a76e79131fdf8761c3fe81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d4906153d6565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b7301c81c93f38f42497b4cebfa23eeb03f7ccfa8c781565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615442565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060120160159054906101000a900460ff1660ff161461067657600080fd5b60006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b8152600401610700919061508e565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610746919061553f565b905060078160008151811061075e5761075d615588565b5b60200260200101510361119557600060018260018151811061078357610782615588565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906155e6565b610806565b60036000858152602001908152602001600020600501546003600086815260200190815260200160002060040154610805919061561a565b5b905061081061488e565b60036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060120160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b81602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c6919061508e565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c919061553f565b905060606000600667ffffffffffffffff811115610a2d57610a2c614e59565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a88615588565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf615588565b5b6020026020010181815250508481600281518110610ae157610ae0615588565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b17615588565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e615588565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b85615588565b5b602002602001018181525050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf19695949392919061564e565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906156f0565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613aa5565b600084602001511115610d1657610d15846020015184613aa5565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d46615588565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d76615588565b5b6020026020010151886060015187600181518110610d9857610d97615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e13615588565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e43615588565b5b6020026020010151886040015187600381518110610e6557610e64615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d919061561a565b9050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f849695949392919061574c565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc591906157ad565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613aa5565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e6140c0565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613aa5565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa615588565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d576003600087815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b91509150736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663ad148af486848760028151811061130657611305615588565b5b60200260200101518860028151811061132257611321615588565b5b60200260200101516040518563ffffffff1660e01b81526004016113499493929190615800565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a9190615845565b925060008360ff16111561142857336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613aa5565b600061147886848760028151811061144d5761144c615588565b5b6020026020010151858960038151811061146a57611469615588565b5b60200260200101518f6140c0565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906155e6565b61416d565b505050505b505050565b611527614926565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508781610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503381610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600080736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b8152600401611662989796959493929190615872565b608060405180830381865afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a391906158f0565b866102800187610260018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610280015160ff16146116e057600080fd5b6116ee338c848d85896140c0565b836000018181525050600080815461170590615957565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119503382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b611993614926565b6000600267ffffffffffffffff8111156119b0576119af614e59565b5b6040519080825280602002602001820160405280156119de5781602001602082028036833780820191505090505b509050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611a3e9998979695949392919061599f565b606060405180830381865afa158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f91906157ad565b846102800184600081518110611a9857611a97615588565b5b6020026020010185600181518110611ab357611ab2615588565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610280015160ff1603611afe578a8c809c50819d505050606482610280019060ff16908160ff16815250505b606482610280015160ff1614611b1357600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a82610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503382610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610260019060ff16908160ff16815250506000808154611c1c90615957565b91905081905550600080549050600082600081518110611c3f57611c3e615588565b5b60200260200101511115611ca657611c8033846101e001518d86610200015186600081518110611c7257611c71615588565b5b60200260200101518a6140c0565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611cbc57611cbb615588565b5b60200260200101511115611d2357611cfd3384610200015184600181518110611ce857611ce7615588565b5b6020026020010151866101e001518e896140c0565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050611f453382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001015492506000830361203257600167ffffffffffffffff811115611ffc57611ffb614e59565b5b60405190808252806020026020018201604052801561202a5781602001602082028036833780820191505090505b509050612639565b600080600e846120429190615a2c565b67ffffffffffffffff81111561205b5761205a614e59565b5b6040519080825280602002602001820160405280156120895781602001602082028036833780820191505090505b50905060005b8481101561263257600086031561263257858284806120ad90615957565b9550815181106120c0576120bf615588565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000015482848061212c90615957565b95508151811061213f5761213e615588565b5b6020026020010181815250506003600087815260200190815260200160002060120160149054906101000a900460ff1660ff1682848061217e90615957565b95508151811061219157612190615588565b5b60200260200101818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b815260040161221a929190615a86565b600060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612260919061553f565b90508060008151811061227657612275615588565b5b602002602001015183858061228a90615957565b96508151811061229d5761229c615588565b5b602002602001018181525050806001815181106122bd576122bc615588565b5b60200260200101518385806122d190615957565b9650815181106122e4576122e3615588565b5b6020026020010181815250508060028151811061230457612303615588565b5b602002602001015183858061231890615957565b96508151811061232b5761232a615588565b5b6020026020010181815250508060038151811061234b5761234a615588565b5b602002602001015183858061235f90615957565b96508151811061237257612371615588565b5b60200260200101818152505060036000888152602001908152602001600020600901548385806123a190615957565b9650815181106123b4576123b3615588565b5b60200260200101818152505060036000888152602001908152602001600020600a01548385806123e390615957565b9650815181106123f6576123f5615588565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061242590615957565b96508151811061243857612437615588565b5b60200260200101818152505060036000888152602001908152602001600020600d015483858061246790615957565b96508151811061247a57612479615588565b5b60200260200101818152505060036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168385806124df90615957565b9650815181106124f2576124f1615588565b5b6020026020010181815250506003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061255790615957565b96508151811061256a57612569615588565b5b6020026020010181815250506003600088815260200190815260200160002060120160159054906101000a900460ff1660ff168385806125a990615957565b9650815181106125bc576125bb615588565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088815260200190815260200160002060010154965050808061262a90615957565b91505061208f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161273557600080fd5b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060648160ff1614158015612775575060c88160ff1614155b156127be576127bd82336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b5b60c88160ff161461295a5760006003600084815260200190815260200160002060000154905060006003600085815260200190815260200160002060010154905060008211156128ab5760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b8152600401612857919061508e565b600060405180830381865afa158015612874573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061289d919061553f565b90506128a98382613aa5565b505b60008111156129575760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b8152600401612903919061508e565b600060405180830381865afa158015612920573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612949919061553f565b90506129558282613aa5565b505b50505b61296433836143d3565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160009055600e820160009055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160146101000a81549060ff02191690556012820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612aef614926565b60036000838152602001908152602001600020604051806102a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016011820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160149054906101000a900460ff1660ff1660ff1681526020016012820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612d4561488e565b612d4d61488e565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060120160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612db357819250505061381c565b60007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e02919061508e565b600060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e48919061553f565b9050600781600081518110612e6057612e5f615588565b5b6020026020010151036135c2576000600182600181518110612e8557612e84615588565b5b602002602001015114612ecf5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612eca91906155e6565b612f08565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f07919061561a565b5b9050600060036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060120160149054906101000a900460ff1660ff16036135155784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061309f5761309e615588565b5b6020026020010151036132e0576130f78560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866130f2919061561a565b6145a4565b90506131238560400151600360008781526020019081526020016000206002015487606001518461464c565b85600001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b8152600401613191919061508e565b600060405180830381865afa1580156131ae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906131d7919061553f565b905060006001826000815181106131f1576131f0615588565b5b60200260200101511480613220575060068260008151811061321657613215615588565b5b6020026020010151145b80613246575060098260008151811061323c5761323b615588565b5b6020026020010151145b613266576003600087815260200190815260200160002060030154613283565b8160038151811061327a57613279615588565b5b60200260200101515b90506132ba87608001518860a0015183600360008b815260200190815260200160002060050154886132b591906155e6565b6145a4565b92506132d08760800151848960a001518461464c565b8760200181815250505050613510565b61332b85608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661332691906155e6565b6145a4565b90506133578560800151828760a00151600360008981526020019081526020016000206003015461464c565b85602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016133c5919061508e565b600060405180830381865afa1580156133e2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061340b919061553f565b9050600060018260008151811061342557613424615588565b5b60200260200101511480613454575060068260008151811061344a57613449615588565b5b6020026020010151145b8061347a57506009826000815181106134705761346f615588565b5b6020026020010151145b61349a5760036000878152602001908152602001600020600201546134b7565b816002815181106134ae576134ad615588565b5b60200260200101515b90506134ee8760400151886060015183600360008b815260200190815260200160002060050154886134e9919061561a565b6145a4565b925061350487604001518289606001518661464c565b87600001818152505050505b6135bb565b60006003600086815260200190815260200160002060030154600360008781526020019081526020016000206002015461354f919061561a565b90506135658660400151876060015183866145a4565b915060018460018151811061357d5761357c615588565b5b602002602001015114613591578181613594565b80825b80935081925050506135b086604001518288606001518561464c565b866000018181525050505b5050613815565b6009816000815181106135d8576135d7615588565b5b60200260200101510361381457846003600084815260200190815260200160002060000154036136e35760036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506137c0565b6003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b61380a8360400151826002815181106137dc576137db615588565b5b60200260200101518560600151846003815181106137fd576137fc615588565b5b602002602001015161464c565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146138b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138a8906153d6565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b7311d5db9473a6e017ba4d182987bc5ab198c04a1581565b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060008160ff161161399f57600080fd5b60648160ff16141580156139b7575060c88160ff1614155b6139c057600080fd5b6003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613a2e57600080fd5b613a7182336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b60646003600084815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050565b60006001600084815260200190815260200160002054905060006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613cb55760036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613ba457613ba3615588565b5b60200260200101511115613cb05784600481518110613bc657613bc5615588565b5b6020026020010151600360008681526020019081526020016000206009016000828254613bf3919061561a565b9250508190555084600581518110613c0e57613c0d615588565b5b602002602001015160036000868152602001908152602001600020600a016000828254613c3b919061561a565b92505081905550600085600681518110613c5857613c57615588565b5b60200260200101511115613caf5784600681518110613c7a57613c79615588565b5b602002602001015160036000868152602001908152602001600020600b016000828254613ca7919061561a565b925050819055505b5b613e4e565b6003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d4157613d40615588565b5b60200260200101511115613e4d5784600481518110613d6357613d62615588565b5b602002602001015160036000868152602001908152602001600020600c016000828254613d90919061561a565b9250508190555084600581518110613dab57613daa615588565b5b602002602001015160036000868152602001908152602001600020600d016000828254613dd8919061561a565b92505081905550600085600681518110613df557613df4615588565b5b60200260200101511115613e4c5784600681518110613e1757613e16615588565b5b602002602001015160036000868152602001908152602001600020600e016000828254613e44919061561a565b925050819055505b5b5b600085600581518110613e6457613e63615588565b5b60200260200101511115613e9957613e98818487600581518110613e8b57613e8a615588565b5b60200260200101516146f4565b5b6000600167ffffffffffffffff811115613eb657613eb5614e59565b5b604051908082528060200260200182016040528015613ee45781602001602082028036833780820191505090505b509050600086600281518110613efd57613efc615588565b5b60200260200101511115613fe9578681600081518110613f2057613f1f615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613f799190614e1c565b6000604051808303816000875af1158015613f98573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613fc1919061553f565b50613fe8838588600281518110613fdb57613fda615588565b5b60200260200101516146f4565b5b8681600081518110613ffe57613ffd615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016140579190614e1c565b6000604051808303816000875af1158015614076573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061409f919061553f565b50600160008881526020019081526020016000206000905550505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b815260040161411a96959493929190615aaf565b6020604051808303816000875af1158015614139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415d9190615b10565b9050809150509695505050505050565b60007301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b81526004016141c093929190615b3d565b6020604051808303816000875af11580156141df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142039190615b10565b90508060036000878152602001908152602001600020600801600082825461422b919061561a565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016145fa9493929190615800565b6040805180830381865afa158015614616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463a9190615b74565b90508091505080915050949350505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016146a29493929190615bb4565b6040805180830381865afa1580156146be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146e29190615b74565b90508091505080915050949350505050565b6000823b90506000811115614808578373ffffffffffffffffffffffffffffffffffffffff1663095ea7b330846040518363ffffffff1660e01b815260040161473e929190615bf9565b6020604051808303816000875af115801561475d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147819190615c4e565b508373ffffffffffffffffffffffffffffffffffffffff166323b872dd3085856040518463ffffffff1660e01b81526004016147bf93929190615b3d565b6020604051808303816000875af11580156147de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148029190615c4e565b50614888565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401614843929190615bf9565b6020604051808303816000875af1158015614862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148869190615c4e565b505b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b604051806102a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614a4f82614a24565b9050919050565b614a5f81614a44565b82525050565b6000602082019050614a7a6000830184614a56565b92915050565b6000604051905090565b600080fd5b600080fd5b614a9d81614a44565b8114614aa857600080fd5b50565b600081359050614aba81614a94565b92915050565b600060208284031215614ad657614ad5614a8a565b5b6000614ae484828501614aab565b91505092915050565b6000819050919050565b614b0081614aed565b8114614b0b57600080fd5b50565b600081359050614b1d81614af7565b92915050565b600080600060608486031215614b3c57614b3b614a8a565b5b6000614b4a86828701614b0e565b9350506020614b5b86828701614b0e565b9250506040614b6c86828701614b0e565b9150509250925092565b600080600080600080600080610100898b031215614b9757614b96614a8a565b5b6000614ba58b828c01614aab565b9850506020614bb68b828c01614aab565b9750506040614bc78b828c01614b0e565b9650506060614bd88b828c01614b0e565b9550506080614be98b828c01614b0e565b94505060a0614bfa8b828c01614b0e565b93505060c0614c0b8b828c01614b0e565b92505060e0614c1c8b828c01614b0e565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614c5057614c4f614a8a565b5b6000614c5e8d828e01614aab565b9a50506020614c6f8d828e01614aab565b9950506040614c808d828e01614b0e565b9850506060614c918d828e01614b0e565b9750506080614ca28d828e01614b0e565b96505060a0614cb38d828e01614b0e565b95505060c0614cc48d828e01614b0e565b94505060e0614cd58d828e01614b0e565b935050610100614ce78d828e01614b0e565b925050610120614cf98d828e01614b0e565b9150509295989b9194979a5092959850565b600080600060608486031215614d2457614d23614a8a565b5b6000614d3286828701614aab565b9350506020614d4386828701614b0e565b9250506040614d5486828701614b0e565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d9381614aed565b82525050565b6000614da58383614d8a565b60208301905092915050565b6000602082019050919050565b6000614dc982614d5e565b614dd38185614d69565b9350614dde83614d7a565b8060005b83811015614e0f578151614df68882614d99565b9750614e0183614db1565b925050600181019050614de2565b5085935050505092915050565b60006020820190508181036000830152614e368184614dbe565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614e9182614e48565b810181811067ffffffffffffffff82111715614eb057614eaf614e59565b5b80604052505050565b6000614ec3614a80565b9050614ecf8282614e88565b919050565b600067ffffffffffffffff821115614eef57614eee614e59565b5b614ef882614e48565b9050602081019050919050565b82818337600083830152505050565b6000614f27614f2284614ed4565b614eb9565b905082815260208101848484011115614f4357614f42614e43565b5b614f4e848285614f05565b509392505050565b600082601f830112614f6b57614f6a614e3e565b5b8135614f7b848260208601614f14565b91505092915050565b600080600060608486031215614f9d57614f9c614a8a565b5b6000614fab86828701614aab565b9350506020614fbc86828701614b0e565b925050604084013567ffffffffffffffff811115614fdd57614fdc614a8f565b5b614fe986828701614f56565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61502881614ff3565b82525050565b6000602082019050615043600083018461501f565b92915050565b60008115159050919050565b61505e81615049565b82525050565b60006020820190506150796000830184615055565b92915050565b61508881614aed565b82525050565b60006020820190506150a3600083018461507f565b92915050565b6000602082840312156150bf576150be614a8a565b5b60006150cd84828501614b0e565b91505092915050565b6150df81614a44565b82525050565b600060ff82169050919050565b6150fb816150e5565b82525050565b6102a0820160008201516151186000850182614d8a565b50602082015161512b6020850182614d8a565b50604082015161513e6040850182614d8a565b5060608201516151516060850182614d8a565b5060808201516151646080850182614d8a565b5060a082015161517760a0850182614d8a565b5060c082015161518a60c0850182614d8a565b5060e082015161519d60e0850182614d8a565b506101008201516151b2610100850182614d8a565b506101208201516151c7610120850182614d8a565b506101408201516151dc610140850182614d8a565b506101608201516151f1610160850182614d8a565b50610180820151615206610180850182614d8a565b506101a082015161521b6101a0850182614d8a565b506101c08201516152306101c0850182614d8a565b506101e08201516152456101e08501826150d6565b5061020082015161525a6102008501826150d6565b5061022082015161526f6102208501826150d6565b506102408201516152846102408501826150d6565b506102608201516152996102608501826150f2565b506102808201516152ae6102808501826150f2565b50505050565b60006102a0820190506152ca6000830184615101565b92915050565b60e0820160008201516152e66000850182614d8a565b5060208201516152f96020850182614d8a565b50604082015161530c60408501826150d6565b50606082015161531f60608501826150d6565b50608082015161533260808501826150d6565b5060a082015161534560a08501826150d6565b5060c082015161535860c08501826150f2565b50505050565b600060e08201905061537360008301846152d0565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006153c0601883615379565b91506153cb8261538a565b602082019050919050565b600060208201905081810360008301526153ef816153b3565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b600061542c601983615379565b9150615437826153f6565b602082019050919050565b6000602082019050818103600083015261545b8161541f565b9050919050565b600067ffffffffffffffff82111561547d5761547c614e59565b5b602082029050602081019050919050565b600080fd5b6000815190506154a281614af7565b92915050565b60006154bb6154b684615462565b614eb9565b905080838252602082019050602084028301858111156154de576154dd61548e565b5b835b8181101561550757806154f38882615493565b8452602084019350506020810190506154e0565b5050509392505050565b600082601f83011261552657615525614e3e565b5b81516155368482602086016154a8565b91505092915050565b60006020828403121561555557615554614a8a565b5b600082015167ffffffffffffffff81111561557357615572614a8f565b5b61557f84828501615511565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006155f182614aed565b91506155fc83614aed565b9250828203905081811115615614576156136155b7565b5b92915050565b600061562582614aed565b915061563083614aed565b9250828201905080821115615648576156476155b7565b5b92915050565b600060c0820190506156636000830189614a56565b6156706020830188614a56565b61567d6040830187614a56565b818103606083015261568f8186614dbe565b905081810360808301526156a38185614dbe565b905081810360a08301526156b78184614dbe565b9050979650505050505050565b6156cd816150e5565b81146156d857600080fd5b50565b6000815190506156ea816156c4565b92915050565b6000806040838503121561570757615706614a8a565b5b6000615715858286016156db565b925050602083015167ffffffffffffffff81111561573657615735614a8f565b5b61574285828601615511565b9150509250929050565b600060c0820190506157616000830189614a56565b61576e6020830188614a56565b61577b6040830187614a56565b615788606083018661507f565b615795608083018561507f565b6157a260a083018461507f565b979650505050505050565b6000806000606084860312156157c6576157c5614a8a565b5b60006157d4868287016156db565b93505060206157e586828701615493565b92505060406157f686828701615493565b9150509250925092565b60006080820190506158156000830187614a56565b6158226020830186614a56565b61582f604083018561507f565b61583c606083018461507f565b95945050505050565b60006020828403121561585b5761585a614a8a565b5b6000615869848285016156db565b91505092915050565b600061010082019050615888600083018b614a56565b615895602083018a614a56565b6158a26040830189614a56565b6158af606083018861507f565b6158bc608083018761507f565b6158c960a083018661507f565b6158d660c083018561507f565b6158e360e083018461507f565b9998505050505050505050565b6000806000806080858703121561590a57615909614a8a565b5b6000615918878288016156db565b9450506020615929878288016156db565b935050604061593a87828801615493565b925050606061594b87828801615493565b91505092959194509250565b600061596282614aed565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615994576159936155b7565b5b600182019050919050565b6000610120820190506159b5600083018c614a56565b6159c2602083018b614a56565b6159cf604083018a614a56565b6159dc606083018961507f565b6159e9608083018861507f565b6159f660a083018761507f565b615a0360c083018661507f565b615a1060e083018561507f565b615a1e61010083018461507f565b9a9950505050505050505050565b6000615a3782614aed565b9150615a4283614aed565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a7b57615a7a6155b7565b5b828202905092915050565b6000604082019050615a9b600083018561507f565b615aa8602083018461507f565b9392505050565b600060c082019050615ac46000830189614a56565b615ad16020830188614a56565b615ade604083018761507f565b615aeb6060830186614a56565b615af8608083018561507f565b615b0560a083018461507f565b979650505050505050565b600060208284031215615b2657615b25614a8a565b5b6000615b3484828501615493565b91505092915050565b6000606082019050615b526000830186614a56565b615b5f6020830185614a56565b615b6c604083018461507f565b949350505050565b60008060408385031215615b8b57615b8a614a8a565b5b6000615b99858286016156db565b9250506020615baa85828601615493565b9150509250929050565b6000608082019050615bc96000830187614a56565b615bd6602083018661507f565b615be36040830185614a56565b615bf0606083018461507f565b95945050505050565b6000604082019050615c0e6000830185614a56565b615c1b602083018461507f565b9392505050565b615c2b81615049565b8114615c3657600080fd5b50565b600081519050615c4881615c22565b92915050565b600060208284031215615c6457615c63614a8a565b5b6000615c7284828501615c39565b9150509291505056fea26469706673582212208bf560699041302fdf0ffe26c519debb442e5d35f90bd1e014428b716756e7f064736f6c63430008100033