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:00.906959Z
Contract source code
// All rights reserved.
// SPDX-License-Identifier: No License (None)
pragma solidity ^0.8.16;
interface IContractBotsHelp {
function checkApproveAndBalance(address _owner, address _token_in, uint _value_in, uint _value_inc_balance) external view returns (uint8);
function checkCreateBotSellBuy(address _owner, address _token_in, address _token_out, uint _value, uint _value_inc, uint _price, uint _price_step, uint _price_limit) external view returns (uint8, uint8, uint256, uint256);
function checkCreateBotNetTrade(address _owner, address _token_in, address _token_out, uint _value_sell, uint _value_buy, uint _price, uint _price_step, uint _price_up_limit, uint _price_down_limit) external view returns (uint8, uint256, uint256);
function checkSchemeBotSellBuy(address _owner, address _token_in, address _token_out, uint _value, uint _price, uint _price_limit) external view returns (uint8, uint256, uint256);
function checkSchemeBotNetTrade(address _owner, address _token_in, address _token_out, uint[] memory _param, uint[] memory _order_data, uint[] memory _order_data_2) external view returns (uint8, uint[] memory);
}
interface IContractDeposits {
function createOrderBot(address _owner, address _token_in, uint _value_in, address _token_out, uint _value_out, uint _order_position) external returns (uint256);
function getTypeAndPriceOrder(address _token_in, uint _value_in, address _token_out, uint _value_out) external view returns (uint8, uint256);
function getTypeAndValue(address _token_in, address _token_out, uint _value, uint _price) external view returns (uint8, uint256);
function getWrappedAndPricelimit() external view returns (address, uint256, uint256);
function payTheOracle(address _owner, address _oracle, uint _gasUsed) external returns (uint256);
}
interface IContractOrders {
function cancelOrders(uint[] memory _id_arr) external returns (uint [] memory);
function deleteCloseOrders(uint[] memory _id_arr) external returns (uint [] memory);
function getLockedTokensForOracle(uint _id1, uint _id2) external view returns (uint [] memory);
function getOrderDataForOracle(uint _id) external view returns (uint [] memory);
}
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
}
contract TwoBearsBots {
struct ListID{
uint256 time; // время создания бота / время частичного исполнения ордера
uint256 next; // указатель на следующий id
uint256 prev; // указатель на предыдущий id
}
struct BotID{
uint256 id_sell; // ID ордера продажи // ID ордера
uint256 id_buy; // ID ордера покупки // 0
uint256 value_sell; // количество продажи // Количество
uint256 value_buy; // количество покупки // Увеличение количества
uint256 price; // цена исполнения // Цена
uint256 price_step; // ценовой шаг (изменение цены после каждого успешно выполненого ордера). Зависит от типа ордера // Ценовой шаг
uint256 price_up_limit; // верхний предел цены при котором бот прекращает работу // Предел цены
uint256 price_down_limit; // нижний предел цены при котором бот прекращает работу // 0
uint256 paid_for_gas; // было заплачено за газ в нативной монете
uint256 gave_1; // было отдано первого токена // отдано
uint256 received_2; // было получено второго токена // получено
uint256 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 = 0xC36755F64E372870Ede6f02360495e0f55C3E0E7; // Контракт с депозитами
address public constant contractOrders = 0xF9875BaDA6eD22c9d9f2926d9cC47dFb007633C7; // Контракт с книгами ордеров
address public constant contractBotsHelp = 0xB9356054732329Cb2096e0d16ccC5677813B1040; // Вспомогательный контракт ботов
event CreateBot(uint indexed ID);
event DeleteBot(uint indexed ID);
event AddOracle(address indexed oracle);
event DeleteOracle(address indexed oracle);
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this");
_;
}
modifier onlyOracle() {
require(oracles[msg.sender] == true, "Only oracle can call this");
_;
}
// Обработаем функции получения нативной монеты и любых токенов ERC223
receive() external payable {} // принимаем нативную монету
function tokenReceived(address _from, uint _value, bytes memory _data) public returns (bytes4) { // принимаем токены ERC223
return this.tokenReceived.selector; // возвращаем селектор этой функции
}
// Работа с ботами
function createBotSellBuy(address _token_in, address _token_out, uint _value, uint _value_inc, uint _price, uint _price_step, uint _price_limit, uint _order_position) external { // создание бота распродажи / закупа
// _value - объем токена с наименьшим приоритетом
// _price - цена в токене с максимальным приоритетом
require(msg.sender == tx.origin, "Only EOA"); // Другие контракты не могут создавать бота
BotID memory _bot;
_bot.value_sell = _value; // Количество
_bot.value_buy = _value_inc; // Увеличение количества
_bot.price = _price; // Цена
_bot.price_step = _price_step; // Ценовой шаг
_bot.price_up_limit = _price_limit; // Предел цены
_bot.token_in = _token_in; // токен который отдает владелец
_bot.token_out = _token_out; // токен который получает владелец
_bot.owner = msg.sender; // владелец бота
uint256 _value_in;
uint256 _value_out;
(_bot.bot_status, _bot.bot_type, _value_in, _value_out) = IContractBotsHelp(contractBotsHelp).checkCreateBotSellBuy(msg.sender, _token_in, _token_out, _value, _value_inc, _price, _price_step, _price_limit);
require(_bot.bot_status == 100); // Проверка создания бота должна быть успешна
// Создаем торгового бота с выставлением первого ордера
_bot.id_sell = createOrderBot(msg.sender, _token_in, _value_in, _token_out, _value_out, _order_position);
++id; // новый ID для создаваемого бота
uint _id = id;
id_bots[_id] = _bot; // сохраняем схему бота
ids[_bot.id_sell] = _id; // привязываем открытый ордер к боту
add_ID_bot(msg.sender, _id); // добавление нового бота в список владельца
emit CreateBot(_id);
}
function createBotNetTrade(address _token_in, address _token_out, uint _value_sell, uint _value_buy, uint _price, uint _price_step, uint _price_up_limit, uint _price_down_limit, uint _order_position_sell, uint _order_position_buy) external { // создание бота сеточной торговли
// _value_sell и _value_buy - объем токена с наименьшим приоритетом
// _price - цена в токене с максимальным приоритетом
// _token_in - будет установлен токен с минимальным приоритетом (сперва идет ордер продажи, а затем ордер покупки)
require(msg.sender == tx.origin, "Only EOA"); // Другие контракты не могут создавать бота
BotID memory _bot;
uint[] memory _values = new uint[](2); // получаем токена с макс. приоритером при продаже, отдаем токен с макс. приоритером при покупке
(_bot.bot_status, _values[0], _values[1]) = IContractBotsHelp(contractBotsHelp).checkCreateBotNetTrade(msg.sender, _token_in, _token_out, _value_sell, _value_buy, _price, _price_step, _price_up_limit, _price_down_limit);
if(_bot.bot_status == 101){ // проверка создания бота - успешна, но входящий и выходящий токена нужно поменять местами, так как сперва мы будем создавать ордер продажи, а затем ордер покупки
(_token_in, _token_out) = (_token_out, _token_in); // входящий и выходящий токены меняем местами
_bot.bot_status = 100;
}
require(_bot.bot_status == 100); // Проверка создания бота должна быть успешна
// Заполняем схему бота
_bot.value_sell = _value_sell; // количество продажи
_bot.value_buy = _value_buy; // количество покупки
_bot.price = _price; // промежуточная цена (между ордером исполнения и ордером продажи)
_bot.price_step = _price_step; // ценовой шаг
_bot.price_up_limit = _price_up_limit; // верхний предел цены при котором бот прекращает работу
_bot.price_down_limit = _price_down_limit; // нижний предел цены при котором бот прекращает работу
_bot.token_in = _token_in; // токен который отдает владелец
_bot.token_out = _token_out; // токен который получает владелец
_bot.owner = msg.sender; // владелец бота
_bot.bot_type = 3; // тип бота. 3 - сеточная торговля
// Создаем торгового бота с выставлением ордеров
++id; // новый ID для создаваемого бота
uint _id = id;
if(_values[0] > 0){ // необходимо создать ордер продажи
_bot.id_sell = createOrderBot(msg.sender, _bot.token_in, _value_sell, _bot.token_out, _values[0], _order_position_sell);
ids[_bot.id_sell] = _id; // привязываем открытый ордер продажи к боту
}
if(_values[1] > 0){ // необходимо создать ордер покупки
_bot.id_buy = createOrderBot(msg.sender, _bot.token_out, _values[1], _bot.token_in, _value_buy, _order_position_buy);
ids[_bot.id_buy] = _id; // привязываем открытый ордер покупки к боту
}
id_bots[_id] = _bot; // сохраняем схему бота
add_ID_bot(msg.sender, _id); // добавление нового бота в список владельца
emit CreateBot(_id);
}
// Вспомогательные функции ========================================
function createOrderBot(address _owner, address _token_in, uint _value_in, address _token_out, uint _value_out, uint _order_position) private returns (uint256){ // создание ордера от имени бота
uint _id_ord = IContractDeposits(contractDeposits).createOrderBot(_owner, _token_in, _value_in, _token_out, _value_out, _order_position);
return _id_ord;
}
function getTypeAndValue(address _token_in, address _token_out, uint _value, uint _price) private view returns (uint256) // вернуть объем токена с наивысшим приоритетом
{
uint256 _value_max_priority;
(, _value_max_priority) = IContractDeposits(contractDeposits).getTypeAndValue(_token_in, _token_out, _value, _price);
return (_value_max_priority);
}
function getTypeAndPriceOrder(address _token_in, uint _value_in, address _token_out, uint _value_out) private view returns (uint256) // вернуть цену ордера
{
uint256 _price;
(, _price) = IContractDeposits(contractDeposits).getTypeAndPriceOrder(_token_in, _value_in, _token_out, _value_out);
return (_price);
}
function payTheOracle(uint _id_bot, address _owner, address _oracle, uint _gasUsed) private { // оплатить работу оракула
uint _value = IContractDeposits(contractDeposits).payTheOracle(_owner, _oracle, _gasUsed); // возвращаем сколько по факту получил оракул
id_bots[_id_bot].paid_for_gas += _value; // обновляем статистику бота по газовым затратам
}
function transfer(address _token, address _recipient, uint _value) private { // перевод токена с баланса этого контракта
IERC20(_token).transfer(_recipient, _value);
}
// =================================================================
function add_ID_bot(address _owner, uint _id_bot) private { // добавление нового бота в список владельца
uint _id_last = bots[_owner][0].prev; // получаем последнего созданного бота владельца
bots[_owner][_id_last].next = _id_bot;
bots[_owner][0].prev = _id_bot;
bots[_owner][_id_bot] = ListID(block.timestamp, 0, _id_last);
}
function del_ID_bot(address _owner, uint _id_bot) private { // удаление бота из списка владельца
uint _id_next = bots[_owner][_id_bot].next;
uint _id_prev = bots[_owner][_id_bot].prev;
bots[_owner][_id_prev].next = _id_next;
bots[_owner][_id_next].prev = _id_prev;
delete bots[_owner][_id_bot];
}
function getBotByID(uint _id_bot) public view returns (BotID memory) // Возвращаем бота по ID
{
return (id_bots[_id_bot]);
}
function getAllBotsOwner(address _owner, uint _id_bot, uint _amount) public view returns (uint [] memory) // Возвращаем указанное количество ботов пользователя, со следующего ордера от стартового ID
{ // если _id_bot = 0, тогда информация по ботам формируются с самого первого бота
/* возвращаемый массив 3 - тип: возвращаемый массив 1,2 - тип:
[
ID_бота, ID_бота,
время_создания, время_создания,
тип бота, тип бота,
адрес_токена_1, адрес_токена_1,
заблокированное_количество_1, заблокированное_количество_1,
адрес_токена_2, адрес_токена_2,
заблокированное_количество_2, заблокированное_количество_2,
отдано_1_токена, отдано,
получено_2_токена, получено,
отдано_2_токена, 0,
получено_1_токена, 0,
адрес_отдаваемого_токена, адрес_отдаваемого_токена,
адрес_получаемого_токена_2, адрес_получаемого_токена,
статус_бота, статус_бота,
...]
*/
_id_bot = bots[_owner][_id_bot].next;
if(_id_bot == 0) return (new uint[](1)); // если открытых ботов еще не существует, либо если это первый бот в списке, который уже был обработан, вернем [0]
uint _index;
uint[] memory result = new uint[](_amount * 14); // возвращаемый массив
for(uint i; i < _amount; i++){
if(_id_bot == 0) break;
result[_index++] = _id_bot;
result[_index++] = bots[_owner][_id_bot].time;
result[_index++] = id_bots[_id_bot].bot_type;
uint[] memory _lock_tokens = IContractOrders(contractOrders).getLockedTokensForOracle(id_bots[_id_bot].id_sell, id_bots[_id_bot].id_buy); // [токен1, количество1, токен2, количество2]
result[_index++] = _lock_tokens[0];
result[_index++] = _lock_tokens[1];
result[_index++] = _lock_tokens[2];
result[_index++] = _lock_tokens[3];
result[_index++] = id_bots[_id_bot].gave_1;
result[_index++] = id_bots[_id_bot].received_2;
result[_index++] = id_bots[_id_bot].gave_2;
result[_index++] = id_bots[_id_bot].received_1;
result[_index++] = uint256(uint160(id_bots[_id_bot].token_in));
result[_index++] = uint256(uint160(id_bots[_id_bot].token_out));
result[_index++] = id_bots[_id_bot].bot_status;
_id_bot = bots[_owner][_id_bot].next;
}
return (result);
}
// Функция проверки ордера (для получения данных оракулом)
function checkOrderByOracle(uint _id_order) public view returns (DataOracle memory) { // Возвращаем необходимые данные по боту для поиска ценовых позиций в книгах ордеров.
DataOracle memory _data;
uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
_data.bot_status = id_bots[_id_bot].bot_status; // Определяем текущий статус бота
if(_data.bot_status != 100) return (_data); // если бот неактивен или не существует
uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен
// определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой)
uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step;
uint _value_max_priority; // объем токена с максимальным приоритетом
_data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота
_data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота
if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли
(_data.token_in_2, _data.token_out_2) = (_data.token_out_1, _data.token_in_1); // Инвертируем токены (для покупки)
if(_order_data[1] == 1){ // данный ордер - продажа
// следующий ордер продажи
_value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, id_bots[_id_bot].value_sell, _price_temp + id_bots[_id_bot].price_step);
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, id_bots[_id_bot].value_sell, _data.token_out_1, _value_max_priority);
// следующий ордер покупки
uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_buy); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[3] : id_bots[_id_bot].value_buy; // определяем объем покупки. Если ордер покупки был со статусом 1, 6 или 9, тогда на покупку идет оставщийся, недокупленный объем
_value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, _val, _price_temp - id_bots[_id_bot].price_step);
_data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, _val);
}
else{ // данный ордер - покупка
// следующий ордер покупки
_value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, id_bots[_id_bot].value_buy, _price_temp - id_bots[_id_bot].price_step);
_data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, id_bots[_id_bot].value_buy);
// следующий ордер продажи
uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_sell); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[2] : id_bots[_id_bot].value_sell; // определяем объем продажи. Если ордер продажи был со статусом 1, 6 или 9, тогда на продажу идет оставщийся, непроданный объем
_value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _val, _price_temp + id_bots[_id_bot].price_step);
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _val, _data.token_out_1, _value_max_priority);
}
}
else{ // бот распродажи или закупа
uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем)
_value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _value, _price_temp);
(_value, _value_max_priority) = (_order_data[1] == 1) ? (_value, _value_max_priority) : (_value_max_priority, _value);
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _value, _data.token_out_1, _value_max_priority);
}
} else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров)
if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
_data.token_in_1 = id_bots[_id_bot].token_in;
_data.token_out_1 = id_bots[_id_bot].token_out;
}
else{ // это покупка у сеточного бота
_data.token_in_1 = id_bots[_id_bot].token_out;
_data.token_out_1 = id_bots[_id_bot].token_in;
}
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _order_data[2], _data.token_out_1, _order_data[3]);
}
return (_data);
}
function workBot(uint _id_order, uint _order_position_1, uint _order_position_2) external onlyOracle { // основная функция оракула (двигатель ботов)
uint _gasUsed = gasleft(); // начинаем расчет газа для оракула
//require(msg.sender == tx.origin, "Only EOA"); // Другие контракты не могут быть оракулом
uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
require(id_bots[_id_bot].bot_status == 100); // статус бота должен быть 100 - активен
address _owner = id_bots[_id_bot].owner; // Владелец бота
uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен
// определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой)
uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step;
DataOracle memory _data;
_data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота
_data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота
if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли
// _data.price_2 - ID второго ордера из схемы ботов
_data.price_2 = (id_bots[_id_bot].id_sell == _id_order) ? id_bots[_id_bot].id_buy : id_bots[_id_bot].id_sell;
// получим данные второго ордера
uint[] memory _order_data_2 = IContractOrders(contractOrders).getOrderDataForOracle(_data.price_2); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки
uint[] memory _param = new uint[](6); // [количество_продажи, количество_покупки, цена, шаг, верхний_предел_цены, нижний_предел_цены]
_param[0] = id_bots[_id_bot].value_sell;
_param[1] = id_bots[_id_bot].value_buy;
_param[2] = _price_temp;
_param[3] = id_bots[_id_bot].price_step;
_param[4] = id_bots[_id_bot].price_up_limit;
_param[5] = id_bots[_id_bot].price_down_limit;
(_data.bot_status, _result) = IContractBotsHelp(contractBotsHelp).checkSchemeBotNetTrade(_owner, _data.token_in_1, _data.token_out_1, _param, _order_data, _order_data_2);
if(_data.bot_status > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете
id_bots[_id_bot].oracle = msg.sender; // оракул
id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки
return;
}
// Удаляем ордера и отвязываем их от ботов
deleteOrder(_id_order, _order_data); // удаляем ордер со статусом 7
if(_data.price_2 > 0){ // если второй ордер существует
deleteOrder(_data.price_2, _order_data_2); // удаляем второй ордер с отвязкой его от бота
}
id_bots[_id_bot].price = _price_temp; // текущая цена
// Создаем новые ордера согласно схеме бота
//uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки
if(_result[0] > 0){ // нужно создавать ордер продажи
uint _ord = _order_position_1; // позиция ордера продажи
_ord = createOrderBot(_owner, _data.token_in_1, _result[0], _data.token_out_1, _result[1], _ord);
ids[_ord] = _id_bot; // привязываем открытый ордер продажи к боту
id_bots[_id_bot].id_sell = _ord;
}
else{ // ордер продажи создавать не нужно, он вышел за верхний предел
id_bots[_id_bot].id_sell = 0;
}
if(_result[2] > 0){ // нужно создавать ордер покупки
uint _ord = _order_position_2; // позиция ордера покупки
_ord = createOrderBot(_owner, _data.token_out_1, _result[2], _data.token_in_1, _result[3], _ord);
ids[_ord] = _id_bot; // привязываем открытый ордер покупки к боту
id_bots[_id_bot].id_buy = _ord;
}
else{ // ордер продажи создавать не нужно, он вышел за верхний предел
id_bots[_id_bot].id_buy = 0;
}
}
else{ // бот распродажи или закупа
// _data.price_1 - количество входящего токена. _data.price_2 - количество выходящего токена
uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем)
(_data.bot_status, _data.price_1, _data.price_2) = IContractBotsHelp(contractBotsHelp).checkSchemeBotSellBuy(_owner, _data.token_in_1, _data.token_out_1, _value, _price_temp, id_bots[_id_bot].price_up_limit);
if(_data.bot_status == 100){ // нужно создавать новый ордер. Схема активна
deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
id_bots[_id_bot].value_sell = _value; // текущее количество токена
id_bots[_id_bot].price = _price_temp; // текущая цена
// создадим новый ордер схемы. _value - ID ордера
_value = createOrderBot(_owner, _data.token_in_1, _data.price_1, _data.token_out_1, _data.price_2, _order_position_1);
ids[_value] = _id_bot; // привязываем открытый ордер продажи к боту
id_bots[_id_bot].id_sell = _value;
} else if (_data.bot_status == 200) { // Схема бота полностью отработала
deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
id_bots[_id_bot].id_sell = 0;
id_bots[_id_bot].bot_status = 200; // статус бота 200 - бот полностью завершил схему
} else{ // возникла ошибка в работе схемы бота
id_bots[_id_bot].oracle = msg.sender; // оракул
id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки
return;
}
}
} else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров)
uint8 _err; // Для возврата кода ошибки;
(address _token_in, address _token_out) = (id_bots[_id_bot].id_sell == _id_order) ? (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out) : (id_bots[_id_bot].token_out, id_bots[_id_bot].token_in); // входящий токен обрабатываемого ордера
_err = IContractBotsHelp(contractBotsHelp).checkApproveAndBalance(_owner, _token_in, _order_data[2], _order_data[2]);
if(_err > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете
id_bots[_id_bot].oracle = msg.sender; // оракул - создатель транзакции
id_bots[_id_bot].bot_status = _err; // статус бота принимает код ошибки
return;
}
deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
uint _new_order = createOrderBot(_owner, _token_in, _order_data[2], _token_out, _order_data[3], _order_position_1);
ids[_new_order] = _id_bot; // привязываем открытый ордер продажи к боту
if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
id_bots[_id_bot].id_sell = _new_order;
}
else{ // это покупка у сеточного бота
id_bots[_id_bot].id_buy = _new_order;
}
} else{ // оракул пытается обработать ордер без статуса 7 или 9. Газ такому оракулу не компенсируем
return;
}
// Оплачиваем работу оракула
payTheOracle(_id_bot, _owner, msg.sender, _gasUsed - gasleft()); // оплата работы оракула
}
function deleteOrder(uint _id_order, uint[] memory _order_data) private { // выплачиваем все по ордеру, обновляем статистику бота, удаляем ордер и отвязываем его от бота
// _order_data - массив данных по ордеру [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
address _owner = id_bots[_id_bot].owner; // Владелец бота
address _token_in; // входящий токен ордера
address _token_out; // выходящий токен ордера
if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
(_token_in, _token_out) = (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out);
if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен)
id_bots[_id_bot].gave_1 += _order_data[4]; // отдал при обмене - первого токена
id_bots[_id_bot].received_2 += _order_data[5]; // получил при обмене - второго токена
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
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50615ce380620000766000396000f3fe6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b6040516101309190614a2b565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b9190614a86565b61044d565b005b34801561016e57600080fd5b5061017761057b565b6040516101849190614a2b565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af9190614ae9565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614b3c565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614bf2565b6119f9565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614cd1565b61205d565b60405161023c9190614de2565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614f4a565b61271c565b6040516102799190614ff4565b60405180910390f35b34801561028e57600080fd5b5061029761272f565b6040516102a49190614a2b565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf9190614a86565b612755565b6040516102e1919061502a565b60405180910390f35b3480156102f657600080fd5b506102ff6127ab565b60405161030c9190615054565b60405180910390f35b34801561032157600080fd5b5061033c6004803603810190610337919061506f565b6127b1565b005b34801561034a57600080fd5b506103656004803603810190610360919061506f565b612bc3565b604051610372919061527a565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d919061506f565b612e19565b6040516103af9190615324565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190614a86565b6138fd565b005b3480156103ed57600080fd5b506103f6613a2b565b6040516104039190614a2b565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e919061506f565b613a43565b005b73b9356054732329cb2096e0d16ccc5677813b104081565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d49061539c565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b73c36755f64e372870ede6f02360495e0f55c3e0e781565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615408565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060120160159054906101000a900460ff1660ff161461067657600080fd5b60006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b81526004016107009190615054565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107469190615505565b905060078160008151811061075e5761075d61554e565b5b6020026020010151036111955760006001826001815181106107835761078261554e565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906155ac565b610806565b6003600085815260200190815260200160002060050154600360008681526020019081526020016000206004015461080591906155e0565b5b9050610810614854565b60036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060120160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b816020018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c69190615054565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c9190615505565b905060606000600667ffffffffffffffff811115610a2d57610a2c614e1f565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a8861554e565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf61554e565b5b6020026020010181815250508481600281518110610ae157610ae061554e565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b1761554e565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e61554e565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b8561554e565b5b60200260200101818152505073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf196959493929190615614565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906156b6565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613b81565b600084602001511115610d1657610d15846020015184613b81565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d4661554e565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d7661554e565b5b6020026020010151886060015187600181518110610d9857610d9761554e565b5b60200260200101518661419c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e1361554e565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e4361554e565b5b6020026020010151886040015187600381518110610e6557610e6461554e565b5b60200260200101518661419c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d91906155e0565b905073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f8496959493929190615712565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc59190615773565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613b81565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e61419c565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613b81565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa61554e565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d576003600087815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b9150915073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663ad148af48684876002815181106113065761130561554e565b5b6020026020010151886002815181106113225761132161554e565b5b60200260200101516040518563ffffffff1660e01b815260040161134994939291906157c6565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a919061580b565b925060008360ff16111561142857336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613b81565b600061147886848760028151811061144d5761144c61554e565b5b6020026020010151858960038151811061146a5761146961554e565b5b60200260200101518f61419c565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906155ac565b614249565b505050505b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461158d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158490615884565b60405180910390fd5b6115956148ec565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508781610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503381610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b81526004016116d09897969594939291906158a4565b608060405180830381865afa1580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117119190615922565b866102800187610260018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610280015160ff161461174e57600080fd5b61175c338c848d858961419c565b836000018181525050600080815461177390615989565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119be3382614315565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5e90615884565b60405180910390fd5b611a6f6148ec565b6000600267ffffffffffffffff811115611a8c57611a8b614e1f565b5b604051908082528060200260200182016040528015611aba5781602001602082028036833780820191505090505b50905073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611b1a999897969594939291906159d1565b606060405180830381865afa158015611b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5b9190615773565b846102800184600081518110611b7457611b7361554e565b5b6020026020010185600181518110611b8f57611b8e61554e565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610280015160ff1603611bda578a8c809c50819d505050606482610280019060ff16908160ff16815250505b606482610280015160ff1614611bef57600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a82610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503382610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610260019060ff16908160ff16815250506000808154611cf890615989565b91905081905550600080549050600082600081518110611d1b57611d1a61554e565b5b60200260200101511115611d8257611d5c33846101e001518d86610200015186600081518110611d4e57611d4d61554e565b5b60200260200101518a61419c565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611d9857611d9761554e565b5b60200260200101511115611dff57611dd93384610200015184600181518110611dc457611dc361554e565b5b6020026020010151866101e001518e8961419c565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff1602179055509050506120213382614315565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001015492506000830361210e57600167ffffffffffffffff8111156120d8576120d7614e1f565b5b6040519080825280602002602001820160405280156121065781602001602082028036833780820191505090505b509050612715565b600080600e8461211e9190615a5e565b67ffffffffffffffff81111561213757612136614e1f565b5b6040519080825280602002602001820160405280156121655781602001602082028036833780820191505090505b50905060005b8481101561270e57600086031561270e578582848061218990615989565b95508151811061219c5761219b61554e565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000015482848061220890615989565b95508151811061221b5761221a61554e565b5b6020026020010181815250506003600087815260200190815260200160002060120160149054906101000a900460ff1660ff1682848061225a90615989565b95508151811061226d5761226c61554e565b5b602002602001018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b81526004016122f6929190615ab8565b600060405180830381865afa158015612313573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061233c9190615505565b9050806000815181106123525761235161554e565b5b602002602001015183858061236690615989565b9650815181106123795761237861554e565b5b602002602001018181525050806001815181106123995761239861554e565b5b60200260200101518385806123ad90615989565b9650815181106123c0576123bf61554e565b5b602002602001018181525050806002815181106123e0576123df61554e565b5b60200260200101518385806123f490615989565b9650815181106124075761240661554e565b5b602002602001018181525050806003815181106124275761242661554e565b5b602002602001015183858061243b90615989565b96508151811061244e5761244d61554e565b5b602002602001018181525050600360008881526020019081526020016000206009015483858061247d90615989565b9650815181106124905761248f61554e565b5b60200260200101818152505060036000888152602001908152602001600020600a01548385806124bf90615989565b9650815181106124d2576124d161554e565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061250190615989565b9650815181106125145761251361554e565b5b60200260200101818152505060036000888152602001908152602001600020600d015483858061254390615989565b9650815181106125565761255561554e565b5b60200260200101818152505060036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168385806125bb90615989565b9650815181106125ce576125cd61554e565b5b6020026020010181815250506003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061263390615989565b9650815181106126465761264561554e565b5b6020026020010181815250506003600088815260200190815260200160002060120160159054906101000a900460ff1660ff1683858061268590615989565b9650815181106126985761269761554e565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088815260200190815260200160002060010154965050808061270690615989565b91505061216b565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161281157600080fd5b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060648160ff1614158015612851575060c88160ff1614155b1561289a5761289982336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000614249565b5b60c88160ff1614612a3657600060036000848152602001908152602001600020600001549050600060036000858152602001908152602001600020600101549050600082111561298757600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b81526004016129339190615054565b600060405180830381865afa158015612950573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906129799190615505565b90506129858382613b81565b505b6000811115612a3357600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b81526004016129df9190615054565b600060405180830381865afa1580156129fc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612a259190615505565b9050612a318282613b81565b505b50505b612a4033836144af565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160009055600e820160009055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160146101000a81549060ff02191690556012820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612bcb6148ec565b60036000838152602001908152602001600020604051806102a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016011820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160149054906101000a900460ff1660ff1660ff1681526020016012820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612e21614854565b612e29614854565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060120160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612e8f5781925050506138f8565b600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612ede9190615054565b600060405180830381865afa158015612efb573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612f249190615505565b9050600781600081518110612f3c57612f3b61554e565b5b60200260200101510361369e576000600182600181518110612f6157612f6061554e565b5b602002602001015114612fab5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612fa691906155ac565b612fe4565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612fe391906155e0565b5b9050600060036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060120160149054906101000a900460ff1660ff16036135f15784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061317b5761317a61554e565b5b6020026020010151036133bc576131d38560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866131ce91906155e0565b614680565b90506131ff85604001516003600087815260200190815260200160002060020154876060015184614728565b856000018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b815260040161326d9190615054565b600060405180830381865afa15801561328a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906132b39190615505565b905060006001826000815181106132cd576132cc61554e565b5b602002602001015114806132fc57506006826000815181106132f2576132f161554e565b5b6020026020010151145b8061332257506009826000815181106133185761331761554e565b5b6020026020010151145b61334257600360008781526020019081526020016000206003015461335f565b816003815181106133565761335561554e565b5b60200260200101515b905061339687608001518860a0015183600360008b8152602001908152602001600020600501548861339191906155ac565b614680565b92506133ac8760800151848960a0015184614728565b87602001818152505050506135ec565b61340785608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661340291906155ac565b614680565b90506134338560800151828760a001516003600089815260200190815260200160002060030154614728565b856020018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016134a19190615054565b600060405180830381865afa1580156134be573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906134e79190615505565b905060006001826000815181106135015761350061554e565b5b6020026020010151148061353057506006826000815181106135265761352561554e565b5b6020026020010151145b80613556575060098260008151811061354c5761354b61554e565b5b6020026020010151145b613576576003600087815260200190815260200160002060020154613593565b8160028151811061358a5761358961554e565b5b60200260200101515b90506135ca8760400151886060015183600360008b815260200190815260200160002060050154886135c591906155e0565b614680565b92506135e0876040015182896060015186614728565b87600001818152505050505b613697565b60006003600086815260200190815260200160002060030154600360008781526020019081526020016000206002015461362b91906155e0565b9050613641866040015187606001518386614680565b91506001846001815181106136595761365861554e565b5b60200260200101511461366d578181613670565b80825b809350819250505061368c866040015182886060015185614728565b866000018181525050505b50506138f1565b6009816000815181106136b4576136b361554e565b5b6020026020010151036138f057846003600084815260200190815260200160002060000154036137bf5760036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061389c565b6003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b6138e68360400151826002815181106138b8576138b761554e565b5b60200260200101518560600151846003815181106138d9576138d861554e565b5b6020026020010151614728565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461398d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139849061539c565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b73f9875bada6ed22c9d9f2926d9cc47dfb007633c781565b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060008160ff1611613a7b57600080fd5b60648160ff1614158015613a93575060c88160ff1614155b613a9c57600080fd5b6003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613b0a57600080fd5b613b4d82336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000614249565b60646003600084815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050565b60006001600084815260200190815260200160002054905060006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613d915760036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613c8057613c7f61554e565b5b60200260200101511115613d8c5784600481518110613ca257613ca161554e565b5b6020026020010151600360008681526020019081526020016000206009016000828254613ccf91906155e0565b9250508190555084600581518110613cea57613ce961554e565b5b602002602001015160036000868152602001908152602001600020600a016000828254613d1791906155e0565b92505081905550600085600681518110613d3457613d3361554e565b5b60200260200101511115613d8b5784600681518110613d5657613d5561554e565b5b602002602001015160036000868152602001908152602001600020600b016000828254613d8391906155e0565b925050819055505b5b613f2a565b6003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613e1d57613e1c61554e565b5b60200260200101511115613f295784600481518110613e3f57613e3e61554e565b5b602002602001015160036000868152602001908152602001600020600c016000828254613e6c91906155e0565b9250508190555084600581518110613e8757613e8661554e565b5b602002602001015160036000868152602001908152602001600020600d016000828254613eb491906155e0565b92505081905550600085600681518110613ed157613ed061554e565b5b60200260200101511115613f285784600681518110613ef357613ef261554e565b5b602002602001015160036000868152602001908152602001600020600e016000828254613f2091906155e0565b925050819055505b5b5b600085600581518110613f4057613f3f61554e565b5b60200260200101511115613f7557613f74818487600581518110613f6757613f6661554e565b5b60200260200101516147d0565b5b6000600167ffffffffffffffff811115613f9257613f91614e1f565b5b604051908082528060200260200182016040528015613fc05781602001602082028036833780820191505090505b509050600086600281518110613fd957613fd861554e565b5b602002602001015111156140c5578681600081518110613ffc57613ffb61554e565b5b60200260200101818152505073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b81526004016140559190614de2565b6000604051808303816000875af1158015614074573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061409d9190615505565b506140c48385886002815181106140b7576140b661554e565b5b60200260200101516147d0565b5b86816000815181106140da576140d961554e565b5b60200260200101818152505073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016141339190614de2565b6000604051808303816000875af1158015614152573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061417b9190615505565b50600160008881526020019081526020016000206000905550505050505050565b60008073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b81526004016141f696959493929190615ae1565b6020604051808303816000875af1158015614215573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142399190615b42565b9050809150509695505050505050565b600073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b815260040161429c93929190615b6f565b6020604051808303816000875af11580156142bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142df9190615b42565b90508060036000878152602001908152602001600020600801600082825461430791906155e0565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b60008073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016146d694939291906157c6565b6040805180830381865afa1580156146f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147169190615ba6565b90508091505080915050949350505050565b60008073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b815260040161477e9493929190615be6565b6040805180830381865afa15801561479a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147be9190615ba6565b90508091505080915050949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b815260040161480b929190615c2b565b6020604051808303816000875af115801561482a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061484e9190615c80565b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b604051806102a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614a15826149ea565b9050919050565b614a2581614a0a565b82525050565b6000602082019050614a406000830184614a1c565b92915050565b6000604051905090565b600080fd5b600080fd5b614a6381614a0a565b8114614a6e57600080fd5b50565b600081359050614a8081614a5a565b92915050565b600060208284031215614a9c57614a9b614a50565b5b6000614aaa84828501614a71565b91505092915050565b6000819050919050565b614ac681614ab3565b8114614ad157600080fd5b50565b600081359050614ae381614abd565b92915050565b600080600060608486031215614b0257614b01614a50565b5b6000614b1086828701614ad4565b9350506020614b2186828701614ad4565b9250506040614b3286828701614ad4565b9150509250925092565b600080600080600080600080610100898b031215614b5d57614b5c614a50565b5b6000614b6b8b828c01614a71565b9850506020614b7c8b828c01614a71565b9750506040614b8d8b828c01614ad4565b9650506060614b9e8b828c01614ad4565b9550506080614baf8b828c01614ad4565b94505060a0614bc08b828c01614ad4565b93505060c0614bd18b828c01614ad4565b92505060e0614be28b828c01614ad4565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614c1657614c15614a50565b5b6000614c248d828e01614a71565b9a50506020614c358d828e01614a71565b9950506040614c468d828e01614ad4565b9850506060614c578d828e01614ad4565b9750506080614c688d828e01614ad4565b96505060a0614c798d828e01614ad4565b95505060c0614c8a8d828e01614ad4565b94505060e0614c9b8d828e01614ad4565b935050610100614cad8d828e01614ad4565b925050610120614cbf8d828e01614ad4565b9150509295989b9194979a5092959850565b600080600060608486031215614cea57614ce9614a50565b5b6000614cf886828701614a71565b9350506020614d0986828701614ad4565b9250506040614d1a86828701614ad4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d5981614ab3565b82525050565b6000614d6b8383614d50565b60208301905092915050565b6000602082019050919050565b6000614d8f82614d24565b614d998185614d2f565b9350614da483614d40565b8060005b83811015614dd5578151614dbc8882614d5f565b9750614dc783614d77565b925050600181019050614da8565b5085935050505092915050565b60006020820190508181036000830152614dfc8184614d84565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614e5782614e0e565b810181811067ffffffffffffffff82111715614e7657614e75614e1f565b5b80604052505050565b6000614e89614a46565b9050614e958282614e4e565b919050565b600067ffffffffffffffff821115614eb557614eb4614e1f565b5b614ebe82614e0e565b9050602081019050919050565b82818337600083830152505050565b6000614eed614ee884614e9a565b614e7f565b905082815260208101848484011115614f0957614f08614e09565b5b614f14848285614ecb565b509392505050565b600082601f830112614f3157614f30614e04565b5b8135614f41848260208601614eda565b91505092915050565b600080600060608486031215614f6357614f62614a50565b5b6000614f7186828701614a71565b9350506020614f8286828701614ad4565b925050604084013567ffffffffffffffff811115614fa357614fa2614a55565b5b614faf86828701614f1c565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614fee81614fb9565b82525050565b60006020820190506150096000830184614fe5565b92915050565b60008115159050919050565b6150248161500f565b82525050565b600060208201905061503f600083018461501b565b92915050565b61504e81614ab3565b82525050565b60006020820190506150696000830184615045565b92915050565b60006020828403121561508557615084614a50565b5b600061509384828501614ad4565b91505092915050565b6150a581614a0a565b82525050565b600060ff82169050919050565b6150c1816150ab565b82525050565b6102a0820160008201516150de6000850182614d50565b5060208201516150f16020850182614d50565b5060408201516151046040850182614d50565b5060608201516151176060850182614d50565b50608082015161512a6080850182614d50565b5060a082015161513d60a0850182614d50565b5060c082015161515060c0850182614d50565b5060e082015161516360e0850182614d50565b50610100820151615178610100850182614d50565b5061012082015161518d610120850182614d50565b506101408201516151a2610140850182614d50565b506101608201516151b7610160850182614d50565b506101808201516151cc610180850182614d50565b506101a08201516151e16101a0850182614d50565b506101c08201516151f66101c0850182614d50565b506101e082015161520b6101e085018261509c565b5061020082015161522061020085018261509c565b5061022082015161523561022085018261509c565b5061024082015161524a61024085018261509c565b5061026082015161525f6102608501826150b8565b506102808201516152746102808501826150b8565b50505050565b60006102a08201905061529060008301846150c7565b92915050565b60e0820160008201516152ac6000850182614d50565b5060208201516152bf6020850182614d50565b5060408201516152d2604085018261509c565b5060608201516152e5606085018261509c565b5060808201516152f8608085018261509c565b5060a082015161530b60a085018261509c565b5060c082015161531e60c08501826150b8565b50505050565b600060e0820190506153396000830184615296565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b600061538660188361533f565b915061539182615350565b602082019050919050565b600060208201905081810360008301526153b581615379565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b60006153f260198361533f565b91506153fd826153bc565b602082019050919050565b60006020820190508181036000830152615421816153e5565b9050919050565b600067ffffffffffffffff82111561544357615442614e1f565b5b602082029050602081019050919050565b600080fd5b60008151905061546881614abd565b92915050565b600061548161547c84615428565b614e7f565b905080838252602082019050602084028301858111156154a4576154a3615454565b5b835b818110156154cd57806154b98882615459565b8452602084019350506020810190506154a6565b5050509392505050565b600082601f8301126154ec576154eb614e04565b5b81516154fc84826020860161546e565b91505092915050565b60006020828403121561551b5761551a614a50565b5b600082015167ffffffffffffffff81111561553957615538614a55565b5b615545848285016154d7565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006155b782614ab3565b91506155c283614ab3565b92508282039050818111156155da576155d961557d565b5b92915050565b60006155eb82614ab3565b91506155f683614ab3565b925082820190508082111561560e5761560d61557d565b5b92915050565b600060c0820190506156296000830189614a1c565b6156366020830188614a1c565b6156436040830187614a1c565b81810360608301526156558186614d84565b905081810360808301526156698185614d84565b905081810360a083015261567d8184614d84565b9050979650505050505050565b615693816150ab565b811461569e57600080fd5b50565b6000815190506156b08161568a565b92915050565b600080604083850312156156cd576156cc614a50565b5b60006156db858286016156a1565b925050602083015167ffffffffffffffff8111156156fc576156fb614a55565b5b615708858286016154d7565b9150509250929050565b600060c0820190506157276000830189614a1c565b6157346020830188614a1c565b6157416040830187614a1c565b61574e6060830186615045565b61575b6080830185615045565b61576860a0830184615045565b979650505050505050565b60008060006060848603121561578c5761578b614a50565b5b600061579a868287016156a1565b93505060206157ab86828701615459565b92505060406157bc86828701615459565b9150509250925092565b60006080820190506157db6000830187614a1c565b6157e86020830186614a1c565b6157f56040830185615045565b6158026060830184615045565b95945050505050565b60006020828403121561582157615820614a50565b5b600061582f848285016156a1565b91505092915050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b600061586e60088361533f565b915061587982615838565b602082019050919050565b6000602082019050818103600083015261589d81615861565b9050919050565b6000610100820190506158ba600083018b614a1c565b6158c7602083018a614a1c565b6158d46040830189614a1c565b6158e16060830188615045565b6158ee6080830187615045565b6158fb60a0830186615045565b61590860c0830185615045565b61591560e0830184615045565b9998505050505050505050565b6000806000806080858703121561593c5761593b614a50565b5b600061594a878288016156a1565b945050602061595b878288016156a1565b935050604061596c87828801615459565b925050606061597d87828801615459565b91505092959194509250565b600061599482614ab3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159c6576159c561557d565b5b600182019050919050565b6000610120820190506159e7600083018c614a1c565b6159f4602083018b614a1c565b615a01604083018a614a1c565b615a0e6060830189615045565b615a1b6080830188615045565b615a2860a0830187615045565b615a3560c0830186615045565b615a4260e0830185615045565b615a50610100830184615045565b9a9950505050505050505050565b6000615a6982614ab3565b9150615a7483614ab3565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615aad57615aac61557d565b5b828202905092915050565b6000604082019050615acd6000830185615045565b615ada6020830184615045565b9392505050565b600060c082019050615af66000830189614a1c565b615b036020830188614a1c565b615b106040830187615045565b615b1d6060830186614a1c565b615b2a6080830185615045565b615b3760a0830184615045565b979650505050505050565b600060208284031215615b5857615b57614a50565b5b6000615b6684828501615459565b91505092915050565b6000606082019050615b846000830186614a1c565b615b916020830185614a1c565b615b9e6040830184615045565b949350505050565b60008060408385031215615bbd57615bbc614a50565b5b6000615bcb858286016156a1565b9250506020615bdc85828601615459565b9150509250929050565b6000608082019050615bfb6000830187614a1c565b615c086020830186615045565b615c156040830185614a1c565b615c226060830184615045565b95945050505050565b6000604082019050615c406000830185614a1c565b615c4d6020830184615045565b9392505050565b615c5d8161500f565b8114615c6857600080fd5b50565b600081519050615c7a81615c54565b92915050565b600060208284031215615c9657615c95614a50565b5b6000615ca484828501615c6b565b9150509291505056fea2646970667358221220d3e858ee407eeac7c1f6b19a7a8ffd7155da926502d0fe76f7e3119884350f8864736f6c63430008100033
Deployed ByteCode
0x6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b6040516101309190614a2b565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b9190614a86565b61044d565b005b34801561016e57600080fd5b5061017761057b565b6040516101849190614a2b565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af9190614ae9565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614b3c565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614bf2565b6119f9565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614cd1565b61205d565b60405161023c9190614de2565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614f4a565b61271c565b6040516102799190614ff4565b60405180910390f35b34801561028e57600080fd5b5061029761272f565b6040516102a49190614a2b565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf9190614a86565b612755565b6040516102e1919061502a565b60405180910390f35b3480156102f657600080fd5b506102ff6127ab565b60405161030c9190615054565b60405180910390f35b34801561032157600080fd5b5061033c6004803603810190610337919061506f565b6127b1565b005b34801561034a57600080fd5b506103656004803603810190610360919061506f565b612bc3565b604051610372919061527a565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d919061506f565b612e19565b6040516103af9190615324565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190614a86565b6138fd565b005b3480156103ed57600080fd5b506103f6613a2b565b6040516104039190614a2b565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e919061506f565b613a43565b005b73b9356054732329cb2096e0d16ccc5677813b104081565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d49061539c565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b73c36755f64e372870ede6f02360495e0f55c3e0e781565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615408565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060120160159054906101000a900460ff1660ff161461067657600080fd5b60006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b81526004016107009190615054565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107469190615505565b905060078160008151811061075e5761075d61554e565b5b6020026020010151036111955760006001826001815181106107835761078261554e565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906155ac565b610806565b6003600085815260200190815260200160002060050154600360008681526020019081526020016000206004015461080591906155e0565b5b9050610810614854565b60036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060120160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b816020018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c69190615054565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c9190615505565b905060606000600667ffffffffffffffff811115610a2d57610a2c614e1f565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a8861554e565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf61554e565b5b6020026020010181815250508481600281518110610ae157610ae061554e565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b1761554e565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e61554e565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b8561554e565b5b60200260200101818152505073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf196959493929190615614565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906156b6565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613b81565b600084602001511115610d1657610d15846020015184613b81565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d4661554e565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d7661554e565b5b6020026020010151886060015187600181518110610d9857610d9761554e565b5b60200260200101518661419c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e1361554e565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e4361554e565b5b6020026020010151886040015187600381518110610e6557610e6461554e565b5b60200260200101518661419c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d91906155e0565b905073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f8496959493929190615712565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc59190615773565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613b81565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e61419c565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613b81565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa61554e565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d576003600087815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b9150915073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663ad148af48684876002815181106113065761130561554e565b5b6020026020010151886002815181106113225761132161554e565b5b60200260200101516040518563ffffffff1660e01b815260040161134994939291906157c6565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a919061580b565b925060008360ff16111561142857336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613b81565b600061147886848760028151811061144d5761144c61554e565b5b6020026020010151858960038151811061146a5761146961554e565b5b60200260200101518f61419c565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906155ac565b614249565b505050505b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461158d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158490615884565b60405180910390fd5b6115956148ec565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508781610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503381610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b81526004016116d09897969594939291906158a4565b608060405180830381865afa1580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117119190615922565b866102800187610260018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610280015160ff161461174e57600080fd5b61175c338c848d858961419c565b836000018181525050600080815461177390615989565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119be3382614315565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5e90615884565b60405180910390fd5b611a6f6148ec565b6000600267ffffffffffffffff811115611a8c57611a8b614e1f565b5b604051908082528060200260200182016040528015611aba5781602001602082028036833780820191505090505b50905073b9356054732329cb2096e0d16ccc5677813b104073ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611b1a999897969594939291906159d1565b606060405180830381865afa158015611b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5b9190615773565b846102800184600081518110611b7457611b7361554e565b5b6020026020010185600181518110611b8f57611b8e61554e565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610280015160ff1603611bda578a8c809c50819d505050606482610280019060ff16908160ff16815250505b606482610280015160ff1614611bef57600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a82610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503382610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610260019060ff16908160ff16815250506000808154611cf890615989565b91905081905550600080549050600082600081518110611d1b57611d1a61554e565b5b60200260200101511115611d8257611d5c33846101e001518d86610200015186600081518110611d4e57611d4d61554e565b5b60200260200101518a61419c565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611d9857611d9761554e565b5b60200260200101511115611dff57611dd93384610200015184600181518110611dc457611dc361554e565b5b6020026020010151866101e001518e8961419c565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff1602179055509050506120213382614315565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001015492506000830361210e57600167ffffffffffffffff8111156120d8576120d7614e1f565b5b6040519080825280602002602001820160405280156121065781602001602082028036833780820191505090505b509050612715565b600080600e8461211e9190615a5e565b67ffffffffffffffff81111561213757612136614e1f565b5b6040519080825280602002602001820160405280156121655781602001602082028036833780820191505090505b50905060005b8481101561270e57600086031561270e578582848061218990615989565b95508151811061219c5761219b61554e565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000015482848061220890615989565b95508151811061221b5761221a61554e565b5b6020026020010181815250506003600087815260200190815260200160002060120160149054906101000a900460ff1660ff1682848061225a90615989565b95508151811061226d5761226c61554e565b5b602002602001018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b81526004016122f6929190615ab8565b600060405180830381865afa158015612313573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061233c9190615505565b9050806000815181106123525761235161554e565b5b602002602001015183858061236690615989565b9650815181106123795761237861554e565b5b602002602001018181525050806001815181106123995761239861554e565b5b60200260200101518385806123ad90615989565b9650815181106123c0576123bf61554e565b5b602002602001018181525050806002815181106123e0576123df61554e565b5b60200260200101518385806123f490615989565b9650815181106124075761240661554e565b5b602002602001018181525050806003815181106124275761242661554e565b5b602002602001015183858061243b90615989565b96508151811061244e5761244d61554e565b5b602002602001018181525050600360008881526020019081526020016000206009015483858061247d90615989565b9650815181106124905761248f61554e565b5b60200260200101818152505060036000888152602001908152602001600020600a01548385806124bf90615989565b9650815181106124d2576124d161554e565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061250190615989565b9650815181106125145761251361554e565b5b60200260200101818152505060036000888152602001908152602001600020600d015483858061254390615989565b9650815181106125565761255561554e565b5b60200260200101818152505060036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168385806125bb90615989565b9650815181106125ce576125cd61554e565b5b6020026020010181815250506003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061263390615989565b9650815181106126465761264561554e565b5b6020026020010181815250506003600088815260200190815260200160002060120160159054906101000a900460ff1660ff1683858061268590615989565b9650815181106126985761269761554e565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088815260200190815260200160002060010154965050808061270690615989565b91505061216b565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161281157600080fd5b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060648160ff1614158015612851575060c88160ff1614155b1561289a5761289982336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000614249565b5b60c88160ff1614612a3657600060036000848152602001908152602001600020600001549050600060036000858152602001908152602001600020600101549050600082111561298757600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b81526004016129339190615054565b600060405180830381865afa158015612950573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906129799190615505565b90506129858382613b81565b505b6000811115612a3357600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b81526004016129df9190615054565b600060405180830381865afa1580156129fc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612a259190615505565b9050612a318282613b81565b505b50505b612a4033836144af565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160009055600e820160009055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160146101000a81549060ff02191690556012820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612bcb6148ec565b60036000838152602001908152602001600020604051806102a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016011820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160149054906101000a900460ff1660ff1660ff1681526020016012820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612e21614854565b612e29614854565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060120160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612e8f5781925050506138f8565b600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612ede9190615054565b600060405180830381865afa158015612efb573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612f249190615505565b9050600781600081518110612f3c57612f3b61554e565b5b60200260200101510361369e576000600182600181518110612f6157612f6061554e565b5b602002602001015114612fab5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612fa691906155ac565b612fe4565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612fe391906155e0565b5b9050600060036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060120160149054906101000a900460ff1660ff16036135f15784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061317b5761317a61554e565b5b6020026020010151036133bc576131d38560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866131ce91906155e0565b614680565b90506131ff85604001516003600087815260200190815260200160002060020154876060015184614728565b856000018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b815260040161326d9190615054565b600060405180830381865afa15801561328a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906132b39190615505565b905060006001826000815181106132cd576132cc61554e565b5b602002602001015114806132fc57506006826000815181106132f2576132f161554e565b5b6020026020010151145b8061332257506009826000815181106133185761331761554e565b5b6020026020010151145b61334257600360008781526020019081526020016000206003015461335f565b816003815181106133565761335561554e565b5b60200260200101515b905061339687608001518860a0015183600360008b8152602001908152602001600020600501548861339191906155ac565b614680565b92506133ac8760800151848960a0015184614728565b87602001818152505050506135ec565b61340785608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661340291906155ac565b614680565b90506134338560800151828760a001516003600089815260200190815260200160002060030154614728565b856020018181525050600073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016134a19190615054565b600060405180830381865afa1580156134be573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906134e79190615505565b905060006001826000815181106135015761350061554e565b5b6020026020010151148061353057506006826000815181106135265761352561554e565b5b6020026020010151145b80613556575060098260008151811061354c5761354b61554e565b5b6020026020010151145b613576576003600087815260200190815260200160002060020154613593565b8160028151811061358a5761358961554e565b5b60200260200101515b90506135ca8760400151886060015183600360008b815260200190815260200160002060050154886135c591906155e0565b614680565b92506135e0876040015182896060015186614728565b87600001818152505050505b613697565b60006003600086815260200190815260200160002060030154600360008781526020019081526020016000206002015461362b91906155e0565b9050613641866040015187606001518386614680565b91506001846001815181106136595761365861554e565b5b60200260200101511461366d578181613670565b80825b809350819250505061368c866040015182886060015185614728565b866000018181525050505b50506138f1565b6009816000815181106136b4576136b361554e565b5b6020026020010151036138f057846003600084815260200190815260200160002060000154036137bf5760036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061389c565b6003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b6138e68360400151826002815181106138b8576138b761554e565b5b60200260200101518560600151846003815181106138d9576138d861554e565b5b6020026020010151614728565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461398d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139849061539c565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b73f9875bada6ed22c9d9f2926d9cc47dfb007633c781565b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060008160ff1611613a7b57600080fd5b60648160ff1614158015613a93575060c88160ff1614155b613a9c57600080fd5b6003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613b0a57600080fd5b613b4d82336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000614249565b60646003600084815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050565b60006001600084815260200190815260200160002054905060006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613d915760036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613c8057613c7f61554e565b5b60200260200101511115613d8c5784600481518110613ca257613ca161554e565b5b6020026020010151600360008681526020019081526020016000206009016000828254613ccf91906155e0565b9250508190555084600581518110613cea57613ce961554e565b5b602002602001015160036000868152602001908152602001600020600a016000828254613d1791906155e0565b92505081905550600085600681518110613d3457613d3361554e565b5b60200260200101511115613d8b5784600681518110613d5657613d5561554e565b5b602002602001015160036000868152602001908152602001600020600b016000828254613d8391906155e0565b925050819055505b5b613f2a565b6003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613e1d57613e1c61554e565b5b60200260200101511115613f295784600481518110613e3f57613e3e61554e565b5b602002602001015160036000868152602001908152602001600020600c016000828254613e6c91906155e0565b9250508190555084600581518110613e8757613e8661554e565b5b602002602001015160036000868152602001908152602001600020600d016000828254613eb491906155e0565b92505081905550600085600681518110613ed157613ed061554e565b5b60200260200101511115613f285784600681518110613ef357613ef261554e565b5b602002602001015160036000868152602001908152602001600020600e016000828254613f2091906155e0565b925050819055505b5b5b600085600581518110613f4057613f3f61554e565b5b60200260200101511115613f7557613f74818487600581518110613f6757613f6661554e565b5b60200260200101516147d0565b5b6000600167ffffffffffffffff811115613f9257613f91614e1f565b5b604051908082528060200260200182016040528015613fc05781602001602082028036833780820191505090505b509050600086600281518110613fd957613fd861554e565b5b602002602001015111156140c5578681600081518110613ffc57613ffb61554e565b5b60200260200101818152505073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b81526004016140559190614de2565b6000604051808303816000875af1158015614074573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061409d9190615505565b506140c48385886002815181106140b7576140b661554e565b5b60200260200101516147d0565b5b86816000815181106140da576140d961554e565b5b60200260200101818152505073f9875bada6ed22c9d9f2926d9cc47dfb007633c773ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016141339190614de2565b6000604051808303816000875af1158015614152573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061417b9190615505565b50600160008881526020019081526020016000206000905550505050505050565b60008073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b81526004016141f696959493929190615ae1565b6020604051808303816000875af1158015614215573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142399190615b42565b9050809150509695505050505050565b600073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b815260040161429c93929190615b6f565b6020604051808303816000875af11580156142bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142df9190615b42565b90508060036000878152602001908152602001600020600801600082825461430791906155e0565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b60008073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016146d694939291906157c6565b6040805180830381865afa1580156146f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147169190615ba6565b90508091505080915050949350505050565b60008073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b815260040161477e9493929190615be6565b6040805180830381865afa15801561479a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147be9190615ba6565b90508091505080915050949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b815260040161480b929190615c2b565b6020604051808303816000875af115801561482a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061484e9190615c80565b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b604051806102a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614a15826149ea565b9050919050565b614a2581614a0a565b82525050565b6000602082019050614a406000830184614a1c565b92915050565b6000604051905090565b600080fd5b600080fd5b614a6381614a0a565b8114614a6e57600080fd5b50565b600081359050614a8081614a5a565b92915050565b600060208284031215614a9c57614a9b614a50565b5b6000614aaa84828501614a71565b91505092915050565b6000819050919050565b614ac681614ab3565b8114614ad157600080fd5b50565b600081359050614ae381614abd565b92915050565b600080600060608486031215614b0257614b01614a50565b5b6000614b1086828701614ad4565b9350506020614b2186828701614ad4565b9250506040614b3286828701614ad4565b9150509250925092565b600080600080600080600080610100898b031215614b5d57614b5c614a50565b5b6000614b6b8b828c01614a71565b9850506020614b7c8b828c01614a71565b9750506040614b8d8b828c01614ad4565b9650506060614b9e8b828c01614ad4565b9550506080614baf8b828c01614ad4565b94505060a0614bc08b828c01614ad4565b93505060c0614bd18b828c01614ad4565b92505060e0614be28b828c01614ad4565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614c1657614c15614a50565b5b6000614c248d828e01614a71565b9a50506020614c358d828e01614a71565b9950506040614c468d828e01614ad4565b9850506060614c578d828e01614ad4565b9750506080614c688d828e01614ad4565b96505060a0614c798d828e01614ad4565b95505060c0614c8a8d828e01614ad4565b94505060e0614c9b8d828e01614ad4565b935050610100614cad8d828e01614ad4565b925050610120614cbf8d828e01614ad4565b9150509295989b9194979a5092959850565b600080600060608486031215614cea57614ce9614a50565b5b6000614cf886828701614a71565b9350506020614d0986828701614ad4565b9250506040614d1a86828701614ad4565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d5981614ab3565b82525050565b6000614d6b8383614d50565b60208301905092915050565b6000602082019050919050565b6000614d8f82614d24565b614d998185614d2f565b9350614da483614d40565b8060005b83811015614dd5578151614dbc8882614d5f565b9750614dc783614d77565b925050600181019050614da8565b5085935050505092915050565b60006020820190508181036000830152614dfc8184614d84565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614e5782614e0e565b810181811067ffffffffffffffff82111715614e7657614e75614e1f565b5b80604052505050565b6000614e89614a46565b9050614e958282614e4e565b919050565b600067ffffffffffffffff821115614eb557614eb4614e1f565b5b614ebe82614e0e565b9050602081019050919050565b82818337600083830152505050565b6000614eed614ee884614e9a565b614e7f565b905082815260208101848484011115614f0957614f08614e09565b5b614f14848285614ecb565b509392505050565b600082601f830112614f3157614f30614e04565b5b8135614f41848260208601614eda565b91505092915050565b600080600060608486031215614f6357614f62614a50565b5b6000614f7186828701614a71565b9350506020614f8286828701614ad4565b925050604084013567ffffffffffffffff811115614fa357614fa2614a55565b5b614faf86828701614f1c565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614fee81614fb9565b82525050565b60006020820190506150096000830184614fe5565b92915050565b60008115159050919050565b6150248161500f565b82525050565b600060208201905061503f600083018461501b565b92915050565b61504e81614ab3565b82525050565b60006020820190506150696000830184615045565b92915050565b60006020828403121561508557615084614a50565b5b600061509384828501614ad4565b91505092915050565b6150a581614a0a565b82525050565b600060ff82169050919050565b6150c1816150ab565b82525050565b6102a0820160008201516150de6000850182614d50565b5060208201516150f16020850182614d50565b5060408201516151046040850182614d50565b5060608201516151176060850182614d50565b50608082015161512a6080850182614d50565b5060a082015161513d60a0850182614d50565b5060c082015161515060c0850182614d50565b5060e082015161516360e0850182614d50565b50610100820151615178610100850182614d50565b5061012082015161518d610120850182614d50565b506101408201516151a2610140850182614d50565b506101608201516151b7610160850182614d50565b506101808201516151cc610180850182614d50565b506101a08201516151e16101a0850182614d50565b506101c08201516151f66101c0850182614d50565b506101e082015161520b6101e085018261509c565b5061020082015161522061020085018261509c565b5061022082015161523561022085018261509c565b5061024082015161524a61024085018261509c565b5061026082015161525f6102608501826150b8565b506102808201516152746102808501826150b8565b50505050565b60006102a08201905061529060008301846150c7565b92915050565b60e0820160008201516152ac6000850182614d50565b5060208201516152bf6020850182614d50565b5060408201516152d2604085018261509c565b5060608201516152e5606085018261509c565b5060808201516152f8608085018261509c565b5060a082015161530b60a085018261509c565b5060c082015161531e60c08501826150b8565b50505050565b600060e0820190506153396000830184615296565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b600061538660188361533f565b915061539182615350565b602082019050919050565b600060208201905081810360008301526153b581615379565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b60006153f260198361533f565b91506153fd826153bc565b602082019050919050565b60006020820190508181036000830152615421816153e5565b9050919050565b600067ffffffffffffffff82111561544357615442614e1f565b5b602082029050602081019050919050565b600080fd5b60008151905061546881614abd565b92915050565b600061548161547c84615428565b614e7f565b905080838252602082019050602084028301858111156154a4576154a3615454565b5b835b818110156154cd57806154b98882615459565b8452602084019350506020810190506154a6565b5050509392505050565b600082601f8301126154ec576154eb614e04565b5b81516154fc84826020860161546e565b91505092915050565b60006020828403121561551b5761551a614a50565b5b600082015167ffffffffffffffff81111561553957615538614a55565b5b615545848285016154d7565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006155b782614ab3565b91506155c283614ab3565b92508282039050818111156155da576155d961557d565b5b92915050565b60006155eb82614ab3565b91506155f683614ab3565b925082820190508082111561560e5761560d61557d565b5b92915050565b600060c0820190506156296000830189614a1c565b6156366020830188614a1c565b6156436040830187614a1c565b81810360608301526156558186614d84565b905081810360808301526156698185614d84565b905081810360a083015261567d8184614d84565b9050979650505050505050565b615693816150ab565b811461569e57600080fd5b50565b6000815190506156b08161568a565b92915050565b600080604083850312156156cd576156cc614a50565b5b60006156db858286016156a1565b925050602083015167ffffffffffffffff8111156156fc576156fb614a55565b5b615708858286016154d7565b9150509250929050565b600060c0820190506157276000830189614a1c565b6157346020830188614a1c565b6157416040830187614a1c565b61574e6060830186615045565b61575b6080830185615045565b61576860a0830184615045565b979650505050505050565b60008060006060848603121561578c5761578b614a50565b5b600061579a868287016156a1565b93505060206157ab86828701615459565b92505060406157bc86828701615459565b9150509250925092565b60006080820190506157db6000830187614a1c565b6157e86020830186614a1c565b6157f56040830185615045565b6158026060830184615045565b95945050505050565b60006020828403121561582157615820614a50565b5b600061582f848285016156a1565b91505092915050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b600061586e60088361533f565b915061587982615838565b602082019050919050565b6000602082019050818103600083015261589d81615861565b9050919050565b6000610100820190506158ba600083018b614a1c565b6158c7602083018a614a1c565b6158d46040830189614a1c565b6158e16060830188615045565b6158ee6080830187615045565b6158fb60a0830186615045565b61590860c0830185615045565b61591560e0830184615045565b9998505050505050505050565b6000806000806080858703121561593c5761593b614a50565b5b600061594a878288016156a1565b945050602061595b878288016156a1565b935050604061596c87828801615459565b925050606061597d87828801615459565b91505092959194509250565b600061599482614ab3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159c6576159c561557d565b5b600182019050919050565b6000610120820190506159e7600083018c614a1c565b6159f4602083018b614a1c565b615a01604083018a614a1c565b615a0e6060830189615045565b615a1b6080830188615045565b615a2860a0830187615045565b615a3560c0830186615045565b615a4260e0830185615045565b615a50610100830184615045565b9a9950505050505050505050565b6000615a6982614ab3565b9150615a7483614ab3565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615aad57615aac61557d565b5b828202905092915050565b6000604082019050615acd6000830185615045565b615ada6020830184615045565b9392505050565b600060c082019050615af66000830189614a1c565b615b036020830188614a1c565b615b106040830187615045565b615b1d6060830186614a1c565b615b2a6080830185615045565b615b3760a0830184615045565b979650505050505050565b600060208284031215615b5857615b57614a50565b5b6000615b6684828501615459565b91505092915050565b6000606082019050615b846000830186614a1c565b615b916020830185614a1c565b615b9e6040830184615045565b949350505050565b60008060408385031215615bbd57615bbc614a50565b5b6000615bcb858286016156a1565b9250506020615bdc85828601615459565b9150509250929050565b6000608082019050615bfb6000830187614a1c565b615c086020830186615045565b615c156040830185614a1c565b615c226060830184615045565b95945050505050565b6000604082019050615c406000830185614a1c565b615c4d6020830184615045565b9392505050565b615c5d8161500f565b8114615c6857600080fd5b50565b600081519050615c7a81615c54565b92915050565b600060208284031215615c9657615c95614a50565b5b6000615ca484828501615c6b565b9150509291505056fea2646970667358221220d3e858ee407eeac7c1f6b19a7a8ffd7155da926502d0fe76f7e3119884350f8864736f6c63430008100033