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:06.981245Z
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 getOrderDataForOracle(uint _id) external view returns (uint [] memory);
}
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
}
contract TwoBearsBots {
struct ListID{
uint256 time; // время создания бота / время частичного исполнения ордера
uint256 next; // указатель на следующий id
uint256 prev; // указатель на предыдущий id
}
struct BotID{
uint256 id_sell; // ID ордера продажи // ID ордера
uint256 id_buy; // ID ордера покупки // 0
uint256 value_sell; // количество продажи // Количество
uint256 value_buy; // количество покупки // Увеличение количества
uint256 price; // цена исполнения // Цена
uint256 price_step; // ценовой шаг (изменение цены после каждого успешно выполненого ордера). Зависит от типа ордера // Ценовой шаг
uint256 price_up_limit; // верхний предел цены при котором бот прекращает работу // Предел цены
uint256 price_down_limit; // нижний предел цены при котором бот прекращает работу // 0
uint256 paid_for_gas; // было заплачено за газ в нативной монете
uint256 gave_1; // было отдано первого токена // отдано
uint256 received_2; // было получено второго токена // получено
uint256 gave_2; // было отдано второго токена // 0
uint256 received_1; // было получено первого токена // 0
address token_in; // токен который отдает владелец // токена который отдает владелец
address token_out; // токен который получает владелец // токена который получает владелец
address owner; // владелец бота // владелец бота
address oracle; // оракул что зафиксировал ошибку бота. Владелец бота должен оплатить работу оракула при снятии блокировки
uint8 bot_type; // тип бота. 1 - распродажа, 2 - закупка, 3 - сеточная торговля // тип бота
uint8 bot_status; // статус бота. 100 - Активен // статус бота
}
struct DataOracle{ // структура возврата данных для оракула, по запрошенному ордеру
uint256 price_1; // первая цена для которой должен быть осуществен поиск позиции
uint256 price_2; // вторая цена для которой должен быть осуществен поиск позиции
address token_in_1; // Адрес первого входящего токена
address token_out_1; // Адрес первого выходящего токена
address token_in_2; // Адрес второго входящего токена
address token_out_2; // Адрес второго выходящего токена
uint8 bot_status; // статус бота. 100 - Активен. При других статусах оракул должен игнорировать ордера данного бота, пока владелец бота не устранит неисправность и не изменит статус на 100
}
uint256 public id; // уникальный идентификатор бота
mapping(uint256 => uint256) private ids; // id_ордера => id_бота
mapping(address => mapping(uint256 => ListID)) private bots; // список всех ботов по владельцам
mapping(uint256 => BotID) private id_bots; // все созданные схемы ботов
mapping(address => bool) private oracles; // доверенные оракулы
address public owner = 0xeBE894814554c8382EA6a24CcDdf1527407A24f6; // Владелец
address public constant contractDeposits = 0x275069215717568faaa7Ea54d0d5C03dBCfBD7D2; // Контракт с депозитами
address public constant contractOrders = 0xb130ED34eaf433b96Ce991179bC36f53c90f6e5C; // Контракт с книгами ордеров
address public constant contractBotsHelp = 0x354974BcceECb7581B1c90Ae09527def0f671b8a; // Вспомогательный контракт ботов
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_бота,
время_создания, время_создания,
тип бота, тип бота,
количество_продажи, Количество,
количество_покупки, Увеличение_количества,
цена, цена,
ценовой_шаг, ценовой_шаг,
верхний_предел, предел_цены,
нижний_предел, 0,
отдано_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 * 16); // возвращаемый массив
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;
result[_index++] = id_bots[_id_bot].value_sell;
result[_index++] = id_bots[_id_bot].value_buy;
result[_index++] = id_bots[_id_bot].price;
result[_index++] = id_bots[_id_bot].price_step;
result[_index++] = id_bots[_id_bot].price_up_limit;
result[_index++] = id_bots[_id_bot].price_down_limit;
result[_index++] = id_bots[_id_bot].gave_1;
result[_index++] = id_bots[_id_bot].received_2;
result[_index++] = id_bots[_id_bot].gave_2;
result[_index++] = id_bots[_id_bot].received_1;
result[_index++] = uint256(uint160(id_bots[_id_bot].token_in));
result[_index++] = uint256(uint160(id_bots[_id_bot].token_out));
result[_index++] = id_bots[_id_bot].bot_status;
_id_bot = bots[_owner][_id_bot].next;
}
return (result);
}
// Функция проверки ордера (для получения данных оракулом)
function checkOrderByOracle(uint _id_order) public view returns (DataOracle memory) { // Возвращаем необходимые данные по боту для поиска ценовых позиций в книгах ордеров.
DataOracle memory _data;
uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
_data.bot_status = id_bots[_id_bot].bot_status; // Определяем текущий статус бота
if(_data.bot_status != 100) return (_data); // если бот неактивен или не существует
uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен
// определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой)
uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step;
uint _value_max_priority; // объем токена с максимальным приоритетом
_data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота
_data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота
if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли
(_data.token_in_2, _data.token_out_2) = (_data.token_out_1, _data.token_in_1); // Инвертируем токены (для покупки)
if(_order_data[1] == 1){ // данный ордер - продажа
// следующий ордер продажи
_value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, id_bots[_id_bot].value_sell, _price_temp + id_bots[_id_bot].price_step);
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, id_bots[_id_bot].value_sell, _data.token_out_1, _value_max_priority);
// следующий ордер покупки
uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_buy); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[3] : id_bots[_id_bot].value_buy; // определяем объем покупки. Если ордер покупки был со статусом 1, 6 или 9, тогда на покупку идет оставщийся, недокупленный объем
_value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, _val, _price_temp - id_bots[_id_bot].price_step);
_data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, _val);
}
else{ // данный ордер - покупка
// следующий ордер покупки
_value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, id_bots[_id_bot].value_buy, _price_temp - id_bots[_id_bot].price_step);
_data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, id_bots[_id_bot].value_buy);
// следующий ордер продажи
uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_sell); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[2] : id_bots[_id_bot].value_sell; // определяем объем продажи. Если ордер продажи был со статусом 1, 6 или 9, тогда на продажу идет оставщийся, непроданный объем
_value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _val, _price_temp + id_bots[_id_bot].price_step);
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _val, _data.token_out_1, _value_max_priority);
}
}
else{ // бот распродажи или закупа
uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем)
_value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _value, _price_temp);
(_value, _value_max_priority) = (_order_data[1] == 1) ? (_value, _value_max_priority) : (_value_max_priority, _value);
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _value, _data.token_out_1, _value_max_priority);
}
} else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров)
if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
_data.token_in_1 = id_bots[_id_bot].token_in;
_data.token_out_1 = id_bots[_id_bot].token_out;
}
else{ // это покупка у сеточного бота
_data.token_in_1 = id_bots[_id_bot].token_out;
_data.token_out_1 = id_bots[_id_bot].token_in;
}
_data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _order_data[2], _data.token_out_1, _order_data[3]);
}
return (_data);
}
function workBot(uint _id_order, uint _order_position_1, uint _order_position_2) external onlyOracle { // основная функция оракула (двигатель ботов)
uint _gasUsed = gasleft(); // начинаем расчет газа для оракула
//require(msg.sender == tx.origin, "Only EOA"); // Другие контракты не могут быть оракулом
uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
require(id_bots[_id_bot].bot_status == 100); // статус бота должен быть 100 - активен
address _owner = id_bots[_id_bot].owner; // Владелец бота
uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен
// определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой)
uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step;
DataOracle memory _data;
_data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота
_data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота
if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли
// _data.price_2 - ID второго ордера из схемы ботов
_data.price_2 = (id_bots[_id_bot].id_sell == _id_order) ? id_bots[_id_bot].id_buy : id_bots[_id_bot].id_sell;
// получим данные второго ордера
uint[] memory _order_data_2 = IContractOrders(contractOrders).getOrderDataForOracle(_data.price_2); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки
uint[] memory _param = new uint[](6); // [количество_продажи, количество_покупки, цена, шаг, верхний_предел_цены, нижний_предел_цены]
_param[0] = id_bots[_id_bot].value_sell;
_param[1] = id_bots[_id_bot].value_buy;
_param[2] = _price_temp;
_param[3] = id_bots[_id_bot].price_step;
_param[4] = id_bots[_id_bot].price_up_limit;
_param[5] = id_bots[_id_bot].price_down_limit;
(_data.bot_status, _result) = IContractBotsHelp(contractBotsHelp).checkSchemeBotNetTrade(_owner, _data.token_in_1, _data.token_out_1, _param, _order_data, _order_data_2);
if(_data.bot_status > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете
id_bots[_id_bot].oracle = msg.sender; // оракул
id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки
return;
}
// Удаляем ордера и отвязываем их от ботов
deleteOrder(_id_order, _order_data); // удаляем ордер со статусом 7
if(_data.price_2 > 0){ // если второй ордер существует
deleteOrder(_data.price_2, _order_data_2); // удаляем второй ордер с отвязкой его от бота
}
id_bots[_id_bot].price = _price_temp; // текущая цена
// Создаем новые ордера согласно схеме бота
//uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки
if(_result[0] > 0){ // нужно создавать ордер продажи
uint _ord = _order_position_1; // позиция ордера продажи
_ord = createOrderBot(_owner, _data.token_in_1, _result[0], _data.token_out_1, _result[1], _ord);
ids[_ord] = _id_bot; // привязываем открытый ордер продажи к боту
id_bots[_id_bot].id_sell = _ord;
}
else{ // ордер продажи создавать не нужно, он вышел за верхний предел
id_bots[_id_bot].id_sell = 0;
}
if(_result[2] > 0){ // нужно создавать ордер покупки
uint _ord = _order_position_2; // позиция ордера покупки
_ord = createOrderBot(_owner, _data.token_out_1, _result[2], _data.token_in_1, _result[3], _ord);
ids[_ord] = _id_bot; // привязываем открытый ордер покупки к боту
id_bots[_id_bot].id_buy = _ord;
}
else{ // ордер продажи создавать не нужно, он вышел за верхний предел
id_bots[_id_bot].id_buy = 0;
}
}
else{ // бот распродажи или закупа
// _data.price_1 - количество входящего токена. _data.price_2 - количество выходящего токена
uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем)
(_data.bot_status, _data.price_1, _data.price_2) = IContractBotsHelp(contractBotsHelp).checkSchemeBotSellBuy(_owner, _data.token_in_1, _data.token_out_1, _value, _price_temp, id_bots[_id_bot].price_up_limit);
if(_data.bot_status == 100){ // нужно создавать новый ордер. Схема активна
deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
id_bots[_id_bot].value_sell = _value; // текущее количество токена
id_bots[_id_bot].price = _price_temp; // текущая цена
// создадим новый ордер схемы. _value - ID ордера
_value = createOrderBot(_owner, _data.token_in_1, _data.price_1, _data.token_out_1, _data.price_2, _order_position_1);
ids[_value] = _id_bot; // привязываем открытый ордер продажи к боту
id_bots[_id_bot].id_sell = _value;
} else if (_data.bot_status == 200) { // Схема бота полностью отработала
deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
id_bots[_id_bot].id_sell = 0;
id_bots[_id_bot].bot_status = 200; // статус бота 200 - бот полностью завершил схему
} else{ // возникла ошибка в работе схемы бота
id_bots[_id_bot].oracle = msg.sender; // оракул
id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки
return;
}
}
} else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров)
uint8 _err; // Для возврата кода ошибки;
(address _token_in, address _token_out) = (id_bots[_id_bot].id_sell == _id_order) ? (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out) : (id_bots[_id_bot].token_out, id_bots[_id_bot].token_in); // входящий токен обрабатываемого ордера
_err = IContractBotsHelp(contractBotsHelp).checkApproveAndBalance(_owner, _token_in, _order_data[2], _order_data[2]);
if(_err > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете
id_bots[_id_bot].oracle = msg.sender; // оракул - создатель транзакции
id_bots[_id_bot].bot_status = _err; // статус бота принимает код ошибки
return;
}
deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
uint _new_order = createOrderBot(_owner, _token_in, _order_data[2], _token_out, _order_data[3], _order_position_1);
ids[_new_order] = _id_bot; // привязываем открытый ордер продажи к боту
if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
id_bots[_id_bot].id_sell = _new_order;
}
else{ // это покупка у сеточного бота
id_bots[_id_bot].id_buy = _new_order;
}
} else{ // оракул пытается обработать ордер без статуса 7 или 9. Газ такому оракулу не компенсируем
return;
}
// Оплачиваем работу оракула
payTheOracle(_id_bot, _owner, msg.sender, _gasUsed - gasleft()); // оплата работы оракула
}
function deleteOrder(uint _id_order, uint[] memory _order_data) private { // выплачиваем все по ордеру, обновляем статистику бота, удаляем ордер и отвязываем его от бота
// _order_data - массив данных по ордеру [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
address _owner = id_bots[_id_bot].owner; // Владелец бота
address _token_in; // входящий токен ордера
address _token_out; // выходящий токен ордера
if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
(_token_in, _token_out) = (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out);
if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен)
id_bots[_id_bot].gave_1 += _order_data[4]; // отдал при обмене - первого токена
id_bots[_id_bot].received_2 += _order_data[5]; // получил при обмене - второго токена
}
}
else{ // это покупка у сеточного бота
(_token_in, _token_out) = (id_bots[_id_bot].token_out, id_bots[_id_bot].token_in);
if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен)
id_bots[_id_bot].gave_2 += _order_data[4]; // отдал при обмене - второго токена
id_bots[_id_bot].received_1 += _order_data[5]; // получил при обмене - первого токена
}
}
// статистика бота обновлена. Делаем возвраты токенов владельцу
if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен), то был получен второй токен
transfer(_token_out, _owner, _order_data[5]); // выплачиваем владельцу бота то что было получено при обмене
}
uint[] memory _arr = new uint[](1); // создаем массив из 1 элемента
if(_order_data[2] > 0){ // если есть необмененый остаток, то отменяем ордер и выплачиваем его
_arr[0] = _id_order; // записываем в него ID ордера
IContractOrders(contractOrders).cancelOrders(_arr); // отменяем ордер для возврата средств на адрес этого контракта
transfer(_token_in, _owner, _order_data[2]); // выплачиваем владельцу бота то что не было обменяно
}
// удаляем отработанный / отмененый ордер. Данный ордер должен быть убран из книги закрытых ордеров
_arr[0] = _id_order; // записываем в массив ID ордера
IContractOrders(contractOrders).deleteCloseOrders(_arr);
delete ids[_id_order]; // разрушаем связь между ордером и ботом
}
function restoreBot(uint _id_bot) external // Восстановление бота. Когда пользователь устранит неисправность бота, он должен вызвать эту функцию чтобы вернуть боту статус 100
{
uint8 _stat = id_bots[_id_bot].bot_status; // получим статус бота
require(_stat > 0); // бот должен существовать
require((_stat != 100) && (_stat != 200)); // Статус бота не должен быть 100 - активен и 200 - бот завершил схему
require(msg.sender == id_bots[_id_bot].owner); // только владелец бота может разблокировать бота
payTheOracle(_id_bot, msg.sender, id_bots[_id_bot].oracle, 0); // оплачиваем газ оракула за обнаружение неисправности бота
id_bots[_id_bot].bot_status = 100; // возобновляем работу бота
}
function deleteBot(uint _id_bot) external // Удаление бота
{
// перед удалением бота автоматически закрываются все ордера и все токены возвращаются владельцу
require(bots[msg.sender][_id_bot].time > 0); // удаляемый бот должен принадлежать владельцу
uint8 _status = id_bots[_id_bot].bot_status; // получим статус бота
if((_status != 100) && (_status != 200)){ // бот находится в состоянии ошибки
payTheOracle(_id_bot, msg.sender, id_bots[_id_bot].oracle, 0); // оплачиваем газ оракула за обнаружение неисправности бота
}
if(_status != 200){ // текущая схема активна, либо бот в состоянии ошибки
uint _id_sell = id_bots[_id_bot].id_sell;
uint _id_buy = id_bots[_id_bot].id_buy;
if(_id_sell > 0){ // Нужно удалять ордер
uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_sell); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
deleteOrder(_id_sell, _order_data); // удаляем ордер с отвязкой его от бота
}
if(_id_buy > 0){ // Нужно удалять ордер
uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_buy); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
deleteOrder(_id_buy, _order_data); // удаляем ордер с отвязкой его от бота
}
}
del_ID_bot(msg.sender, _id_bot); // удаление бота из списка владельца
delete id_bots[_id_bot]; // удаление схемы бота
emit DeleteBot(_id_bot);
}
// ФУНКЦИИ ВЛАДЕЛЬЦА
function addOracle(address _oracle) external onlyOwner // добавить доверенного оракула
{
oracles[_oracle] = true;
emit AddOracle(_oracle);
}
function deleteOracle(address _oracle) external onlyOwner // удалить доверенного оракула
{
oracles[_oracle] = false;
emit DeleteOracle(_oracle);
}
function isOracle(address _oracle) public view returns (bool) // проверяем является ли адрес оракулом
{
return (oracles[_oracle]);
}
}
Contract ABI
[{"type":"event","name":"AddOracle","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"CreateBot","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"DeleteBot","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"DeleteOracle","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TwoBearsBots.DataOracle","components":[{"type":"uint256","name":"price_1","internalType":"uint256"},{"type":"uint256","name":"price_2","internalType":"uint256"},{"type":"address","name":"token_in_1","internalType":"address"},{"type":"address","name":"token_out_1","internalType":"address"},{"type":"address","name":"token_in_2","internalType":"address"},{"type":"address","name":"token_out_2","internalType":"address"},{"type":"uint8","name":"bot_status","internalType":"uint8"}]}],"name":"checkOrderByOracle","inputs":[{"type":"uint256","name":"_id_order","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractBotsHelp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractDeposits","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractOrders","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createBotNetTrade","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_value_sell","internalType":"uint256"},{"type":"uint256","name":"_value_buy","internalType":"uint256"},{"type":"uint256","name":"_price","internalType":"uint256"},{"type":"uint256","name":"_price_step","internalType":"uint256"},{"type":"uint256","name":"_price_up_limit","internalType":"uint256"},{"type":"uint256","name":"_price_down_limit","internalType":"uint256"},{"type":"uint256","name":"_order_position_sell","internalType":"uint256"},{"type":"uint256","name":"_order_position_buy","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createBotSellBuy","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"uint256","name":"_value_inc","internalType":"uint256"},{"type":"uint256","name":"_price","internalType":"uint256"},{"type":"uint256","name":"_price_step","internalType":"uint256"},{"type":"uint256","name":"_price_limit","internalType":"uint256"},{"type":"uint256","name":"_order_position","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteBot","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getAllBotsOwner","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id_bot","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TwoBearsBots.BotID","components":[{"type":"uint256","name":"id_sell","internalType":"uint256"},{"type":"uint256","name":"id_buy","internalType":"uint256"},{"type":"uint256","name":"value_sell","internalType":"uint256"},{"type":"uint256","name":"value_buy","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"price_step","internalType":"uint256"},{"type":"uint256","name":"price_up_limit","internalType":"uint256"},{"type":"uint256","name":"price_down_limit","internalType":"uint256"},{"type":"uint256","name":"paid_for_gas","internalType":"uint256"},{"type":"uint256","name":"gave_1","internalType":"uint256"},{"type":"uint256","name":"received_2","internalType":"uint256"},{"type":"uint256","name":"gave_2","internalType":"uint256"},{"type":"uint256","name":"received_1","internalType":"uint256"},{"type":"address","name":"token_in","internalType":"address"},{"type":"address","name":"token_out","internalType":"address"},{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"oracle","internalType":"address"},{"type":"uint8","name":"bot_type","internalType":"uint8"},{"type":"uint8","name":"bot_status","internalType":"uint8"}]}],"name":"getBotByID","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"id","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"restoreBot","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"workBot","inputs":[{"type":"uint256","name":"_id_order","internalType":"uint256"},{"type":"uint256","name":"_order_position_1","internalType":"uint256"},{"type":"uint256","name":"_order_position_2","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50615b0280620000766000396000f3fe6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b604051610130919061489d565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b91906148f8565b61044d565b005b34801561016e57600080fd5b5061017761057b565b604051610184919061489d565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af919061495b565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d891906149ae565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614a64565b6119e3565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614b43565b612031565b60405161023c9190614c54565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614dbc565b61269a565b6040516102799190614e66565b60405180910390f35b34801561028e57600080fd5b506102976126ad565b6040516102a4919061489d565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf91906148f8565b6126d3565b6040516102e19190614e9c565b60405180910390f35b3480156102f657600080fd5b506102ff612729565b60405161030c9190614ec6565b60405180910390f35b34801561032157600080fd5b5061033c60048036038101906103379190614ee1565b61272f565b005b34801561034a57600080fd5b5061036560048036038101906103609190614ee1565b612b31565b60405161037291906150c2565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d9190614ee1565b612d73565b6040516103af919061516c565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da91906148f8565b613857565b005b3480156103ed57600080fd5b506103f6613985565b604051610403919061489d565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e9190614ee1565b61399d565b005b73354974bcceecb7581b1c90ae09527def0f671b8a81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d4906151e4565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b73275069215717568faaa7ea54d0d5c03dbcfbd7d281565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615250565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060100160159054906101000a900460ff1660ff161461067657600080fd5b600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b81526004016107009190614ec6565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610746919061534d565b905060078160008151811061075e5761075d615396565b5b60200260200101510361119557600060018260018151811061078357610782615396565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906153f4565b610806565b600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546108059190615428565b5b90506108106146d4565b60036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060100160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b816020018181525050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c69190614ec6565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c919061534d565b905060606000600667ffffffffffffffff811115610a2d57610a2c614c91565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a88615396565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf615396565b5b6020026020010181815250508481600281518110610ae157610ae0615396565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b17615396565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e615396565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b85615396565b5b60200260200101818152505073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf19695949392919061545c565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906154fe565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613adb565b600084602001511115610d1657610d15846020015184613adb565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d46615396565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d76615396565b5b6020026020010151886060015187600181518110610d9857610d97615396565b5b60200260200101518661401c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e13615396565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e43615396565b5b6020026020010151886040015187600381518110610e6557610e64615396565b5b60200260200101518661401c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d9190615428565b905073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f849695949392919061555a565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc591906155bb565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613adb565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e61401c565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613adb565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa615396565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d5760036000878152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b9150915073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663ad148af486848760028151811061130657611305615396565b5b60200260200101518860028151811061132257611321615396565b5b60200260200101516040518563ffffffff1660e01b8152600401611349949392919061560e565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a9190615653565b925060008360ff16111561142857336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613adb565b600061147886848760028151811061144d5761144c615396565b5b6020026020010151858960038151811061146a57611469615396565b5b60200260200101518f61401c565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906153f4565b6140c9565b505050505b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461158d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611584906156cc565b60405180910390fd5b61159561476c565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505087816101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b81526004016116d09897969594939291906156ec565b608060405180830381865afa1580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611711919061576a565b866102400187610220018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610240015160ff161461174e57600080fd5b61175c338c848d858961401c565b8360000181815250506000808154611773906157d1565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119a83382614195565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a48906156cc565b60405180910390fd5b611a5961476c565b6000600267ffffffffffffffff811115611a7657611a75614c91565b5b604051908082528060200260200182016040528015611aa45781602001602082028036833780820191505090505b50905073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611b0499989796959493929190615819565b606060405180830381865afa158015611b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4591906155bb565b846102400184600081518110611b5e57611b5d615396565b5b6020026020010185600181518110611b7957611b78615396565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610240015160ff1603611bc4578a8c809c50819d505050606482610240019060ff16908160ff16815250505b606482610240015160ff1614611bd957600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a826101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610220019060ff16908160ff16815250506000808154611ce2906157d1565b91905081905550600080549050600082600081518110611d0557611d04615396565b5b60200260200101511115611d6c57611d4633846101a001518d866101c0015186600081518110611d3857611d37615396565b5b60200260200101518a61401c565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611d8257611d81615396565b5b60200260200101511115611de957611dc333846101c0015184600181518110611dae57611dad615396565b5b6020026020010151866101a001518e8961401c565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050611ff53382614195565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101549250600083036120e257600167ffffffffffffffff8111156120ac576120ab614c91565b5b6040519080825280602002602001820160405280156120da5781602001602082028036833780820191505090505b509050612693565b6000806010846120f291906158a6565b67ffffffffffffffff81111561210b5761210a614c91565b5b6040519080825280602002602001820160405280156121395781602001602082028036833780820191505090505b50905060005b8481101561268c57600086031561268c578582848061215d906157d1565b9550815181106121705761216f615396565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600001548284806121dc906157d1565b9550815181106121ef576121ee615396565b5b6020026020010181815250506003600087815260200190815260200160002060100160149054906101000a900460ff1660ff1682848061222e906157d1565b95508151811061224157612240615396565b5b6020026020010181815250506003600087815260200190815260200160002060020154828480612270906157d1565b95508151811061228357612282615396565b5b60200260200101818152505060036000878152602001908152602001600020600301548284806122b2906157d1565b9550815181106122c5576122c4615396565b5b60200260200101818152505060036000878152602001908152602001600020600401548284806122f4906157d1565b95508151811061230757612306615396565b5b6020026020010181815250506003600087815260200190815260200160002060050154828480612336906157d1565b95508151811061234957612348615396565b5b6020026020010181815250506003600087815260200190815260200160002060060154828480612378906157d1565b95508151811061238b5761238a615396565b5b60200260200101818152505060036000878152602001908152602001600020600701548284806123ba906157d1565b9550815181106123cd576123cc615396565b5b60200260200101818152505060036000878152602001908152602001600020600901548284806123fc906157d1565b95508151811061240f5761240e615396565b5b60200260200101818152505060036000878152602001908152602001600020600a015482848061243e906157d1565b95508151811061245157612450615396565b5b60200260200101818152505060036000878152602001908152602001600020600b0154828480612480906157d1565b95508151811061249357612492615396565b5b60200260200101818152505060036000878152602001908152602001600020600c01548284806124c2906157d1565b9550815181106124d5576124d4615396565b5b60200260200101818152505060036000878152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061253a906157d1565b95508151811061254d5761254c615396565b5b60200260200101818152505060036000878152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168284806125b2906157d1565b9550815181106125c5576125c4615396565b5b6020026020010181815250506003600087815260200190815260200160002060100160159054906101000a900460ff1660ff16828480612604906157d1565b95508151811061261757612616615396565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206001015495508080612684906157d1565b91505061213f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161278f57600080fd5b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060648160ff16141580156127cf575060c88160ff1614155b156128185761281782336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006140c9565b5b60c88160ff16146129b457600060036000848152602001908152602001600020600001549050600060036000858152602001908152602001600020600101549050600082111561290557600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b81526004016128b19190614ec6565b600060405180830381865afa1580156128ce573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906128f7919061534d565b90506129038382613adb565b505b60008111156129b157600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b815260040161295d9190614ec6565b600060405180830381865afa15801561297a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906129a3919061534d565b90506129af8282613adb565b505b50505b6129be338361432f565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600e820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160146101000a81549060ff02191690556010820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612b3961476c565b600360008381526020019081526020016000206040518061026001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600e820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160149054906101000a900460ff1660ff1660ff1681526020016010820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612d7b6146d4565b612d836146d4565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060100160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612de9578192505050613852565b600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e389190614ec6565b600060405180830381865afa158015612e55573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e7e919061534d565b9050600781600081518110612e9657612e95615396565b5b6020026020010151036135f8576000600182600181518110612ebb57612eba615396565b5b602002602001015114612f055760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f0091906153f4565b612f3e565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f3d9190615428565b5b9050600060036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060100160149054906101000a900460ff1660ff160361354b5784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050506001836001815181106130d5576130d4615396565b5b6020026020010151036133165761312d8560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866131289190615428565b614500565b9050613159856040015160036000878152602001908152602001600020600201548760600151846145a8565b856000018181525050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b81526004016131c79190614ec6565b600060405180830381865afa1580156131e4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061320d919061534d565b9050600060018260008151811061322757613226615396565b5b60200260200101511480613256575060068260008151811061324c5761324b615396565b5b6020026020010151145b8061327c575060098260008151811061327257613271615396565b5b6020026020010151145b61329c5760036000878152602001908152602001600020600301546132b9565b816003815181106132b0576132af615396565b5b60200260200101515b90506132f087608001518860a0015183600360008b815260200190815260200160002060050154886132eb91906153f4565b614500565b92506133068760800151848960a00151846145a8565b8760200181815250505050613546565b61336185608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661335c91906153f4565b614500565b905061338d8560800151828760a0015160036000898152602001908152602001600020600301546145a8565b856020018181525050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016133fb9190614ec6565b600060405180830381865afa158015613418573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613441919061534d565b9050600060018260008151811061345b5761345a615396565b5b6020026020010151148061348a57506006826000815181106134805761347f615396565b5b6020026020010151145b806134b057506009826000815181106134a6576134a5615396565b5b6020026020010151145b6134d05760036000878152602001908152602001600020600201546134ed565b816002815181106134e4576134e3615396565b5b60200260200101515b90506135248760400151886060015183600360008b8152602001908152602001600020600501548861351f9190615428565b614500565b925061353a8760400151828960600151866145a8565b87600001818152505050505b6135f1565b6000600360008681526020019081526020016000206003015460036000878152602001908152602001600020600201546135859190615428565b905061359b866040015187606001518386614500565b91506001846001815181106135b3576135b2615396565b5b6020026020010151146135c75781816135ca565b80825b80935081925050506135e68660400151828860600151856145a8565b866000018181525050505b505061384b565b60098160008151811061360e5761360d615396565b5b60200260200101510361384a57846003600084815260200190815260200160002060000154036137195760036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506137f6565b60036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b61384083604001518260028151811061381257613811615396565b5b602002602001015185606001518460038151811061383357613832615396565b5b60200260200101516145a8565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146138e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138de906151e4565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b73b130ed34eaf433b96ce991179bc36f53c90f6e5c81565b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060008160ff16116139d557600080fd5b60648160ff16141580156139ed575060c88160ff1614155b6139f657600080fd5b60036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613a6457600080fd5b613aa782336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006140c9565b60646003600084815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050565b600060016000848152602001908152602001600020549050600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613c7e5760036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613bda57613bd9615396565b5b60200260200101511115613c795784600481518110613bfc57613bfb615396565b5b6020026020010151600360008681526020019081526020016000206009016000828254613c299190615428565b9250508190555084600581518110613c4457613c43615396565b5b602002602001015160036000868152602001908152602001600020600a016000828254613c719190615428565b925050819055505b613daa565b60036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d0a57613d09615396565b5b60200260200101511115613da95784600481518110613d2c57613d2b615396565b5b602002602001015160036000868152602001908152602001600020600b016000828254613d599190615428565b9250508190555084600581518110613d7457613d73615396565b5b602002602001015160036000868152602001908152602001600020600c016000828254613da19190615428565b925050819055505b5b600085600581518110613dc057613dbf615396565b5b60200260200101511115613df557613df4818487600581518110613de757613de6615396565b5b6020026020010151614650565b5b6000600167ffffffffffffffff811115613e1257613e11614c91565b5b604051908082528060200260200182016040528015613e405781602001602082028036833780820191505090505b509050600086600281518110613e5957613e58615396565b5b60200260200101511115613f45578681600081518110613e7c57613e7b615396565b5b60200260200101818152505073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613ed59190614c54565b6000604051808303816000875af1158015613ef4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613f1d919061534d565b50613f44838588600281518110613f3757613f36615396565b5b6020026020010151614650565b5b8681600081518110613f5a57613f59615396565b5b60200260200101818152505073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b8152600401613fb39190614c54565b6000604051808303816000875af1158015613fd2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613ffb919061534d565b50600160008881526020019081526020016000206000905550505050505050565b60008073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b815260040161407696959493929190615900565b6020604051808303816000875af1158015614095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b99190615961565b9050809150509695505050505050565b600073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b815260040161411c9392919061598e565b6020604051808303816000875af115801561413b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415f9190615961565b9050806003600087815260200190815260200160002060080160008282546141879190615428565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b60008073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b8152600401614556949392919061560e565b6040805180830381865afa158015614572573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061459691906159c5565b90508091505080915050949350505050565b60008073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016145fe9493929190615a05565b6040805180830381865afa15801561461a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463e91906159c5565b90508091505080915050949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b815260040161468b929190615a4a565b6020604051808303816000875af11580156146aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ce9190615a9f565b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b60405180610260016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006148878261485c565b9050919050565b6148978161487c565b82525050565b60006020820190506148b2600083018461488e565b92915050565b6000604051905090565b600080fd5b600080fd5b6148d58161487c565b81146148e057600080fd5b50565b6000813590506148f2816148cc565b92915050565b60006020828403121561490e5761490d6148c2565b5b600061491c848285016148e3565b91505092915050565b6000819050919050565b61493881614925565b811461494357600080fd5b50565b6000813590506149558161492f565b92915050565b600080600060608486031215614974576149736148c2565b5b600061498286828701614946565b935050602061499386828701614946565b92505060406149a486828701614946565b9150509250925092565b600080600080600080600080610100898b0312156149cf576149ce6148c2565b5b60006149dd8b828c016148e3565b98505060206149ee8b828c016148e3565b97505060406149ff8b828c01614946565b9650506060614a108b828c01614946565b9550506080614a218b828c01614946565b94505060a0614a328b828c01614946565b93505060c0614a438b828c01614946565b92505060e0614a548b828c01614946565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614a8857614a876148c2565b5b6000614a968d828e016148e3565b9a50506020614aa78d828e016148e3565b9950506040614ab88d828e01614946565b9850506060614ac98d828e01614946565b9750506080614ada8d828e01614946565b96505060a0614aeb8d828e01614946565b95505060c0614afc8d828e01614946565b94505060e0614b0d8d828e01614946565b935050610100614b1f8d828e01614946565b925050610120614b318d828e01614946565b9150509295989b9194979a5092959850565b600080600060608486031215614b5c57614b5b6148c2565b5b6000614b6a868287016148e3565b9350506020614b7b86828701614946565b9250506040614b8c86828701614946565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614bcb81614925565b82525050565b6000614bdd8383614bc2565b60208301905092915050565b6000602082019050919050565b6000614c0182614b96565b614c0b8185614ba1565b9350614c1683614bb2565b8060005b83811015614c47578151614c2e8882614bd1565b9750614c3983614be9565b925050600181019050614c1a565b5085935050505092915050565b60006020820190508181036000830152614c6e8184614bf6565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614cc982614c80565b810181811067ffffffffffffffff82111715614ce857614ce7614c91565b5b80604052505050565b6000614cfb6148b8565b9050614d078282614cc0565b919050565b600067ffffffffffffffff821115614d2757614d26614c91565b5b614d3082614c80565b9050602081019050919050565b82818337600083830152505050565b6000614d5f614d5a84614d0c565b614cf1565b905082815260208101848484011115614d7b57614d7a614c7b565b5b614d86848285614d3d565b509392505050565b600082601f830112614da357614da2614c76565b5b8135614db3848260208601614d4c565b91505092915050565b600080600060608486031215614dd557614dd46148c2565b5b6000614de3868287016148e3565b9350506020614df486828701614946565b925050604084013567ffffffffffffffff811115614e1557614e146148c7565b5b614e2186828701614d8e565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614e6081614e2b565b82525050565b6000602082019050614e7b6000830184614e57565b92915050565b60008115159050919050565b614e9681614e81565b82525050565b6000602082019050614eb16000830184614e8d565b92915050565b614ec081614925565b82525050565b6000602082019050614edb6000830184614eb7565b92915050565b600060208284031215614ef757614ef66148c2565b5b6000614f0584828501614946565b91505092915050565b614f178161487c565b82525050565b600060ff82169050919050565b614f3381614f1d565b82525050565b61026082016000820151614f506000850182614bc2565b506020820151614f636020850182614bc2565b506040820151614f766040850182614bc2565b506060820151614f896060850182614bc2565b506080820151614f9c6080850182614bc2565b5060a0820151614faf60a0850182614bc2565b5060c0820151614fc260c0850182614bc2565b5060e0820151614fd560e0850182614bc2565b50610100820151614fea610100850182614bc2565b50610120820151614fff610120850182614bc2565b50610140820151615014610140850182614bc2565b50610160820151615029610160850182614bc2565b5061018082015161503e610180850182614bc2565b506101a08201516150536101a0850182614f0e565b506101c08201516150686101c0850182614f0e565b506101e082015161507d6101e0850182614f0e565b50610200820151615092610200850182614f0e565b506102208201516150a7610220850182614f2a565b506102408201516150bc610240850182614f2a565b50505050565b6000610260820190506150d86000830184614f39565b92915050565b60e0820160008201516150f46000850182614bc2565b5060208201516151076020850182614bc2565b50604082015161511a6040850182614f0e565b50606082015161512d6060850182614f0e565b5060808201516151406080850182614f0e565b5060a082015161515360a0850182614f0e565b5060c082015161516660c0850182614f2a565b50505050565b600060e08201905061518160008301846150de565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006151ce601883615187565b91506151d982615198565b602082019050919050565b600060208201905081810360008301526151fd816151c1565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b600061523a601983615187565b915061524582615204565b602082019050919050565b600060208201905081810360008301526152698161522d565b9050919050565b600067ffffffffffffffff82111561528b5761528a614c91565b5b602082029050602081019050919050565b600080fd5b6000815190506152b08161492f565b92915050565b60006152c96152c484615270565b614cf1565b905080838252602082019050602084028301858111156152ec576152eb61529c565b5b835b81811015615315578061530188826152a1565b8452602084019350506020810190506152ee565b5050509392505050565b600082601f83011261533457615333614c76565b5b81516153448482602086016152b6565b91505092915050565b600060208284031215615363576153626148c2565b5b600082015167ffffffffffffffff811115615381576153806148c7565b5b61538d8482850161531f565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006153ff82614925565b915061540a83614925565b9250828203905081811115615422576154216153c5565b5b92915050565b600061543382614925565b915061543e83614925565b9250828201905080821115615456576154556153c5565b5b92915050565b600060c082019050615471600083018961488e565b61547e602083018861488e565b61548b604083018761488e565b818103606083015261549d8186614bf6565b905081810360808301526154b18185614bf6565b905081810360a08301526154c58184614bf6565b9050979650505050505050565b6154db81614f1d565b81146154e657600080fd5b50565b6000815190506154f8816154d2565b92915050565b60008060408385031215615515576155146148c2565b5b6000615523858286016154e9565b925050602083015167ffffffffffffffff811115615544576155436148c7565b5b6155508582860161531f565b9150509250929050565b600060c08201905061556f600083018961488e565b61557c602083018861488e565b615589604083018761488e565b6155966060830186614eb7565b6155a36080830185614eb7565b6155b060a0830184614eb7565b979650505050505050565b6000806000606084860312156155d4576155d36148c2565b5b60006155e2868287016154e9565b93505060206155f3868287016152a1565b9250506040615604868287016152a1565b9150509250925092565b6000608082019050615623600083018761488e565b615630602083018661488e565b61563d6040830185614eb7565b61564a6060830184614eb7565b95945050505050565b600060208284031215615669576156686148c2565b5b6000615677848285016154e9565b91505092915050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b60006156b6600883615187565b91506156c182615680565b602082019050919050565b600060208201905081810360008301526156e5816156a9565b9050919050565b600061010082019050615702600083018b61488e565b61570f602083018a61488e565b61571c604083018961488e565b6157296060830188614eb7565b6157366080830187614eb7565b61574360a0830186614eb7565b61575060c0830185614eb7565b61575d60e0830184614eb7565b9998505050505050505050565b60008060008060808587031215615784576157836148c2565b5b6000615792878288016154e9565b94505060206157a3878288016154e9565b93505060406157b4878288016152a1565b92505060606157c5878288016152a1565b91505092959194509250565b60006157dc82614925565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361580e5761580d6153c5565b5b600182019050919050565b60006101208201905061582f600083018c61488e565b61583c602083018b61488e565b615849604083018a61488e565b6158566060830189614eb7565b6158636080830188614eb7565b61587060a0830187614eb7565b61587d60c0830186614eb7565b61588a60e0830185614eb7565b615898610100830184614eb7565b9a9950505050505050505050565b60006158b182614925565b91506158bc83614925565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156158f5576158f46153c5565b5b828202905092915050565b600060c082019050615915600083018961488e565b615922602083018861488e565b61592f6040830187614eb7565b61593c606083018661488e565b6159496080830185614eb7565b61595660a0830184614eb7565b979650505050505050565b600060208284031215615977576159766148c2565b5b6000615985848285016152a1565b91505092915050565b60006060820190506159a3600083018661488e565b6159b0602083018561488e565b6159bd6040830184614eb7565b949350505050565b600080604083850312156159dc576159db6148c2565b5b60006159ea858286016154e9565b92505060206159fb858286016152a1565b9150509250929050565b6000608082019050615a1a600083018761488e565b615a276020830186614eb7565b615a34604083018561488e565b615a416060830184614eb7565b95945050505050565b6000604082019050615a5f600083018561488e565b615a6c6020830184614eb7565b9392505050565b615a7c81614e81565b8114615a8757600080fd5b50565b600081519050615a9981615a73565b92915050565b600060208284031215615ab557615ab46148c2565b5b6000615ac384828501615a8a565b9150509291505056fea2646970667358221220852d90053938a34348c1551b72abbab87a89cea070585ffb423c8713c95e529364736f6c63430008100033
Deployed ByteCode
0x6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b604051610130919061489d565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b91906148f8565b61044d565b005b34801561016e57600080fd5b5061017761057b565b604051610184919061489d565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af919061495b565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d891906149ae565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614a64565b6119e3565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614b43565b612031565b60405161023c9190614c54565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614dbc565b61269a565b6040516102799190614e66565b60405180910390f35b34801561028e57600080fd5b506102976126ad565b6040516102a4919061489d565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf91906148f8565b6126d3565b6040516102e19190614e9c565b60405180910390f35b3480156102f657600080fd5b506102ff612729565b60405161030c9190614ec6565b60405180910390f35b34801561032157600080fd5b5061033c60048036038101906103379190614ee1565b61272f565b005b34801561034a57600080fd5b5061036560048036038101906103609190614ee1565b612b31565b60405161037291906150c2565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d9190614ee1565b612d73565b6040516103af919061516c565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da91906148f8565b613857565b005b3480156103ed57600080fd5b506103f6613985565b604051610403919061489d565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e9190614ee1565b61399d565b005b73354974bcceecb7581b1c90ae09527def0f671b8a81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d4906151e4565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b73275069215717568faaa7ea54d0d5c03dbcfbd7d281565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615250565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060100160159054906101000a900460ff1660ff161461067657600080fd5b600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b81526004016107009190614ec6565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610746919061534d565b905060078160008151811061075e5761075d615396565b5b60200260200101510361119557600060018260018151811061078357610782615396565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906153f4565b610806565b600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546108059190615428565b5b90506108106146d4565b60036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060100160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b816020018181525050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c69190614ec6565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c919061534d565b905060606000600667ffffffffffffffff811115610a2d57610a2c614c91565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a88615396565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf615396565b5b6020026020010181815250508481600281518110610ae157610ae0615396565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b17615396565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e615396565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b85615396565b5b60200260200101818152505073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf19695949392919061545c565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906154fe565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613adb565b600084602001511115610d1657610d15846020015184613adb565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d46615396565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d76615396565b5b6020026020010151886060015187600181518110610d9857610d97615396565b5b60200260200101518661401c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e13615396565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e43615396565b5b6020026020010151886040015187600381518110610e6557610e64615396565b5b60200260200101518661401c565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d9190615428565b905073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f849695949392919061555a565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc591906155bb565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613adb565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e61401c565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613adb565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa615396565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d5760036000878152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b9150915073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663ad148af486848760028151811061130657611305615396565b5b60200260200101518860028151811061132257611321615396565b5b60200260200101516040518563ffffffff1660e01b8152600401611349949392919061560e565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a9190615653565b925060008360ff16111561142857336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613adb565b600061147886848760028151811061144d5761144c615396565b5b6020026020010151858960038151811061146a57611469615396565b5b60200260200101518f61401c565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906153f4565b6140c9565b505050505b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461158d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611584906156cc565b60405180910390fd5b61159561476c565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505087816101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b81526004016116d09897969594939291906156ec565b608060405180830381865afa1580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611711919061576a565b866102400187610220018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610240015160ff161461174e57600080fd5b61175c338c848d858961401c565b8360000181815250506000808154611773906157d1565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119a83382614195565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a48906156cc565b60405180910390fd5b611a5961476c565b6000600267ffffffffffffffff811115611a7657611a75614c91565b5b604051908082528060200260200182016040528015611aa45781602001602082028036833780820191505090505b50905073354974bcceecb7581b1c90ae09527def0f671b8a73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611b0499989796959493929190615819565b606060405180830381865afa158015611b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4591906155bb565b846102400184600081518110611b5e57611b5d615396565b5b6020026020010185600181518110611b7957611b78615396565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610240015160ff1603611bc4578a8c809c50819d505050606482610240019060ff16908160ff16815250505b606482610240015160ff1614611bd957600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a826101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610220019060ff16908160ff16815250506000808154611ce2906157d1565b91905081905550600080549050600082600081518110611d0557611d04615396565b5b60200260200101511115611d6c57611d4633846101a001518d866101c0015186600081518110611d3857611d37615396565b5b60200260200101518a61401c565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611d8257611d81615396565b5b60200260200101511115611de957611dc333846101c0015184600181518110611dae57611dad615396565b5b6020026020010151866101a001518e8961401c565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050611ff53382614195565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101549250600083036120e257600167ffffffffffffffff8111156120ac576120ab614c91565b5b6040519080825280602002602001820160405280156120da5781602001602082028036833780820191505090505b509050612693565b6000806010846120f291906158a6565b67ffffffffffffffff81111561210b5761210a614c91565b5b6040519080825280602002602001820160405280156121395781602001602082028036833780820191505090505b50905060005b8481101561268c57600086031561268c578582848061215d906157d1565b9550815181106121705761216f615396565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600001548284806121dc906157d1565b9550815181106121ef576121ee615396565b5b6020026020010181815250506003600087815260200190815260200160002060100160149054906101000a900460ff1660ff1682848061222e906157d1565b95508151811061224157612240615396565b5b6020026020010181815250506003600087815260200190815260200160002060020154828480612270906157d1565b95508151811061228357612282615396565b5b60200260200101818152505060036000878152602001908152602001600020600301548284806122b2906157d1565b9550815181106122c5576122c4615396565b5b60200260200101818152505060036000878152602001908152602001600020600401548284806122f4906157d1565b95508151811061230757612306615396565b5b6020026020010181815250506003600087815260200190815260200160002060050154828480612336906157d1565b95508151811061234957612348615396565b5b6020026020010181815250506003600087815260200190815260200160002060060154828480612378906157d1565b95508151811061238b5761238a615396565b5b60200260200101818152505060036000878152602001908152602001600020600701548284806123ba906157d1565b9550815181106123cd576123cc615396565b5b60200260200101818152505060036000878152602001908152602001600020600901548284806123fc906157d1565b95508151811061240f5761240e615396565b5b60200260200101818152505060036000878152602001908152602001600020600a015482848061243e906157d1565b95508151811061245157612450615396565b5b60200260200101818152505060036000878152602001908152602001600020600b0154828480612480906157d1565b95508151811061249357612492615396565b5b60200260200101818152505060036000878152602001908152602001600020600c01548284806124c2906157d1565b9550815181106124d5576124d4615396565b5b60200260200101818152505060036000878152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061253a906157d1565b95508151811061254d5761254c615396565b5b60200260200101818152505060036000878152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168284806125b2906157d1565b9550815181106125c5576125c4615396565b5b6020026020010181815250506003600087815260200190815260200160002060100160159054906101000a900460ff1660ff16828480612604906157d1565b95508151811061261757612616615396565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206001015495508080612684906157d1565b91505061213f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161278f57600080fd5b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060648160ff16141580156127cf575060c88160ff1614155b156128185761281782336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006140c9565b5b60c88160ff16146129b457600060036000848152602001908152602001600020600001549050600060036000858152602001908152602001600020600101549050600082111561290557600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b81526004016128b19190614ec6565b600060405180830381865afa1580156128ce573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906128f7919061534d565b90506129038382613adb565b505b60008111156129b157600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b815260040161295d9190614ec6565b600060405180830381865afa15801561297a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906129a3919061534d565b90506129af8282613adb565b505b50505b6129be338361432f565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600e820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160146101000a81549060ff02191690556010820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612b3961476c565b600360008381526020019081526020016000206040518061026001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600e820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160149054906101000a900460ff1660ff1660ff1681526020016010820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612d7b6146d4565b612d836146d4565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060100160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612de9578192505050613852565b600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e389190614ec6565b600060405180830381865afa158015612e55573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e7e919061534d565b9050600781600081518110612e9657612e95615396565b5b6020026020010151036135f8576000600182600181518110612ebb57612eba615396565b5b602002602001015114612f055760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f0091906153f4565b612f3e565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f3d9190615428565b5b9050600060036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060100160149054906101000a900460ff1660ff160361354b5784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050506001836001815181106130d5576130d4615396565b5b6020026020010151036133165761312d8560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866131289190615428565b614500565b9050613159856040015160036000878152602001908152602001600020600201548760600151846145a8565b856000018181525050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b81526004016131c79190614ec6565b600060405180830381865afa1580156131e4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061320d919061534d565b9050600060018260008151811061322757613226615396565b5b60200260200101511480613256575060068260008151811061324c5761324b615396565b5b6020026020010151145b8061327c575060098260008151811061327257613271615396565b5b6020026020010151145b61329c5760036000878152602001908152602001600020600301546132b9565b816003815181106132b0576132af615396565b5b60200260200101515b90506132f087608001518860a0015183600360008b815260200190815260200160002060050154886132eb91906153f4565b614500565b92506133068760800151848960a00151846145a8565b8760200181815250505050613546565b61336185608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661335c91906153f4565b614500565b905061338d8560800151828760a0015160036000898152602001908152602001600020600301546145a8565b856020018181525050600073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016133fb9190614ec6565b600060405180830381865afa158015613418573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613441919061534d565b9050600060018260008151811061345b5761345a615396565b5b6020026020010151148061348a57506006826000815181106134805761347f615396565b5b6020026020010151145b806134b057506009826000815181106134a6576134a5615396565b5b6020026020010151145b6134d05760036000878152602001908152602001600020600201546134ed565b816002815181106134e4576134e3615396565b5b60200260200101515b90506135248760400151886060015183600360008b8152602001908152602001600020600501548861351f9190615428565b614500565b925061353a8760400151828960600151866145a8565b87600001818152505050505b6135f1565b6000600360008681526020019081526020016000206003015460036000878152602001908152602001600020600201546135859190615428565b905061359b866040015187606001518386614500565b91506001846001815181106135b3576135b2615396565b5b6020026020010151146135c75781816135ca565b80825b80935081925050506135e68660400151828860600151856145a8565b866000018181525050505b505061384b565b60098160008151811061360e5761360d615396565b5b60200260200101510361384a57846003600084815260200190815260200160002060000154036137195760036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506137f6565b60036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b61384083604001518260028151811061381257613811615396565b5b602002602001015185606001518460038151811061383357613832615396565b5b60200260200101516145a8565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146138e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138de906151e4565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b73b130ed34eaf433b96ce991179bc36f53c90f6e5c81565b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060008160ff16116139d557600080fd5b60648160ff16141580156139ed575060c88160ff1614155b6139f657600080fd5b60036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613a6457600080fd5b613aa782336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006140c9565b60646003600084815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050565b600060016000848152602001908152602001600020549050600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613c7e5760036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613bda57613bd9615396565b5b60200260200101511115613c795784600481518110613bfc57613bfb615396565b5b6020026020010151600360008681526020019081526020016000206009016000828254613c299190615428565b9250508190555084600581518110613c4457613c43615396565b5b602002602001015160036000868152602001908152602001600020600a016000828254613c719190615428565b925050819055505b613daa565b60036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d0a57613d09615396565b5b60200260200101511115613da95784600481518110613d2c57613d2b615396565b5b602002602001015160036000868152602001908152602001600020600b016000828254613d599190615428565b9250508190555084600581518110613d7457613d73615396565b5b602002602001015160036000868152602001908152602001600020600c016000828254613da19190615428565b925050819055505b5b600085600581518110613dc057613dbf615396565b5b60200260200101511115613df557613df4818487600581518110613de757613de6615396565b5b6020026020010151614650565b5b6000600167ffffffffffffffff811115613e1257613e11614c91565b5b604051908082528060200260200182016040528015613e405781602001602082028036833780820191505090505b509050600086600281518110613e5957613e58615396565b5b60200260200101511115613f45578681600081518110613e7c57613e7b615396565b5b60200260200101818152505073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613ed59190614c54565b6000604051808303816000875af1158015613ef4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613f1d919061534d565b50613f44838588600281518110613f3757613f36615396565b5b6020026020010151614650565b5b8681600081518110613f5a57613f59615396565b5b60200260200101818152505073b130ed34eaf433b96ce991179bc36f53c90f6e5c73ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b8152600401613fb39190614c54565b6000604051808303816000875af1158015613fd2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613ffb919061534d565b50600160008881526020019081526020016000206000905550505050505050565b60008073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b815260040161407696959493929190615900565b6020604051808303816000875af1158015614095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b99190615961565b9050809150509695505050505050565b600073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b815260040161411c9392919061598e565b6020604051808303816000875af115801561413b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415f9190615961565b9050806003600087815260200190815260200160002060080160008282546141879190615428565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b60008073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b8152600401614556949392919061560e565b6040805180830381865afa158015614572573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061459691906159c5565b90508091505080915050949350505050565b60008073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016145fe9493929190615a05565b6040805180830381865afa15801561461a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463e91906159c5565b90508091505080915050949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b815260040161468b929190615a4a565b6020604051808303816000875af11580156146aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ce9190615a9f565b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b60405180610260016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006148878261485c565b9050919050565b6148978161487c565b82525050565b60006020820190506148b2600083018461488e565b92915050565b6000604051905090565b600080fd5b600080fd5b6148d58161487c565b81146148e057600080fd5b50565b6000813590506148f2816148cc565b92915050565b60006020828403121561490e5761490d6148c2565b5b600061491c848285016148e3565b91505092915050565b6000819050919050565b61493881614925565b811461494357600080fd5b50565b6000813590506149558161492f565b92915050565b600080600060608486031215614974576149736148c2565b5b600061498286828701614946565b935050602061499386828701614946565b92505060406149a486828701614946565b9150509250925092565b600080600080600080600080610100898b0312156149cf576149ce6148c2565b5b60006149dd8b828c016148e3565b98505060206149ee8b828c016148e3565b97505060406149ff8b828c01614946565b9650506060614a108b828c01614946565b9550506080614a218b828c01614946565b94505060a0614a328b828c01614946565b93505060c0614a438b828c01614946565b92505060e0614a548b828c01614946565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614a8857614a876148c2565b5b6000614a968d828e016148e3565b9a50506020614aa78d828e016148e3565b9950506040614ab88d828e01614946565b9850506060614ac98d828e01614946565b9750506080614ada8d828e01614946565b96505060a0614aeb8d828e01614946565b95505060c0614afc8d828e01614946565b94505060e0614b0d8d828e01614946565b935050610100614b1f8d828e01614946565b925050610120614b318d828e01614946565b9150509295989b9194979a5092959850565b600080600060608486031215614b5c57614b5b6148c2565b5b6000614b6a868287016148e3565b9350506020614b7b86828701614946565b9250506040614b8c86828701614946565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614bcb81614925565b82525050565b6000614bdd8383614bc2565b60208301905092915050565b6000602082019050919050565b6000614c0182614b96565b614c0b8185614ba1565b9350614c1683614bb2565b8060005b83811015614c47578151614c2e8882614bd1565b9750614c3983614be9565b925050600181019050614c1a565b5085935050505092915050565b60006020820190508181036000830152614c6e8184614bf6565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614cc982614c80565b810181811067ffffffffffffffff82111715614ce857614ce7614c91565b5b80604052505050565b6000614cfb6148b8565b9050614d078282614cc0565b919050565b600067ffffffffffffffff821115614d2757614d26614c91565b5b614d3082614c80565b9050602081019050919050565b82818337600083830152505050565b6000614d5f614d5a84614d0c565b614cf1565b905082815260208101848484011115614d7b57614d7a614c7b565b5b614d86848285614d3d565b509392505050565b600082601f830112614da357614da2614c76565b5b8135614db3848260208601614d4c565b91505092915050565b600080600060608486031215614dd557614dd46148c2565b5b6000614de3868287016148e3565b9350506020614df486828701614946565b925050604084013567ffffffffffffffff811115614e1557614e146148c7565b5b614e2186828701614d8e565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614e6081614e2b565b82525050565b6000602082019050614e7b6000830184614e57565b92915050565b60008115159050919050565b614e9681614e81565b82525050565b6000602082019050614eb16000830184614e8d565b92915050565b614ec081614925565b82525050565b6000602082019050614edb6000830184614eb7565b92915050565b600060208284031215614ef757614ef66148c2565b5b6000614f0584828501614946565b91505092915050565b614f178161487c565b82525050565b600060ff82169050919050565b614f3381614f1d565b82525050565b61026082016000820151614f506000850182614bc2565b506020820151614f636020850182614bc2565b506040820151614f766040850182614bc2565b506060820151614f896060850182614bc2565b506080820151614f9c6080850182614bc2565b5060a0820151614faf60a0850182614bc2565b5060c0820151614fc260c0850182614bc2565b5060e0820151614fd560e0850182614bc2565b50610100820151614fea610100850182614bc2565b50610120820151614fff610120850182614bc2565b50610140820151615014610140850182614bc2565b50610160820151615029610160850182614bc2565b5061018082015161503e610180850182614bc2565b506101a08201516150536101a0850182614f0e565b506101c08201516150686101c0850182614f0e565b506101e082015161507d6101e0850182614f0e565b50610200820151615092610200850182614f0e565b506102208201516150a7610220850182614f2a565b506102408201516150bc610240850182614f2a565b50505050565b6000610260820190506150d86000830184614f39565b92915050565b60e0820160008201516150f46000850182614bc2565b5060208201516151076020850182614bc2565b50604082015161511a6040850182614f0e565b50606082015161512d6060850182614f0e565b5060808201516151406080850182614f0e565b5060a082015161515360a0850182614f0e565b5060c082015161516660c0850182614f2a565b50505050565b600060e08201905061518160008301846150de565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006151ce601883615187565b91506151d982615198565b602082019050919050565b600060208201905081810360008301526151fd816151c1565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b600061523a601983615187565b915061524582615204565b602082019050919050565b600060208201905081810360008301526152698161522d565b9050919050565b600067ffffffffffffffff82111561528b5761528a614c91565b5b602082029050602081019050919050565b600080fd5b6000815190506152b08161492f565b92915050565b60006152c96152c484615270565b614cf1565b905080838252602082019050602084028301858111156152ec576152eb61529c565b5b835b81811015615315578061530188826152a1565b8452602084019350506020810190506152ee565b5050509392505050565b600082601f83011261533457615333614c76565b5b81516153448482602086016152b6565b91505092915050565b600060208284031215615363576153626148c2565b5b600082015167ffffffffffffffff811115615381576153806148c7565b5b61538d8482850161531f565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006153ff82614925565b915061540a83614925565b9250828203905081811115615422576154216153c5565b5b92915050565b600061543382614925565b915061543e83614925565b9250828201905080821115615456576154556153c5565b5b92915050565b600060c082019050615471600083018961488e565b61547e602083018861488e565b61548b604083018761488e565b818103606083015261549d8186614bf6565b905081810360808301526154b18185614bf6565b905081810360a08301526154c58184614bf6565b9050979650505050505050565b6154db81614f1d565b81146154e657600080fd5b50565b6000815190506154f8816154d2565b92915050565b60008060408385031215615515576155146148c2565b5b6000615523858286016154e9565b925050602083015167ffffffffffffffff811115615544576155436148c7565b5b6155508582860161531f565b9150509250929050565b600060c08201905061556f600083018961488e565b61557c602083018861488e565b615589604083018761488e565b6155966060830186614eb7565b6155a36080830185614eb7565b6155b060a0830184614eb7565b979650505050505050565b6000806000606084860312156155d4576155d36148c2565b5b60006155e2868287016154e9565b93505060206155f3868287016152a1565b9250506040615604868287016152a1565b9150509250925092565b6000608082019050615623600083018761488e565b615630602083018661488e565b61563d6040830185614eb7565b61564a6060830184614eb7565b95945050505050565b600060208284031215615669576156686148c2565b5b6000615677848285016154e9565b91505092915050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b60006156b6600883615187565b91506156c182615680565b602082019050919050565b600060208201905081810360008301526156e5816156a9565b9050919050565b600061010082019050615702600083018b61488e565b61570f602083018a61488e565b61571c604083018961488e565b6157296060830188614eb7565b6157366080830187614eb7565b61574360a0830186614eb7565b61575060c0830185614eb7565b61575d60e0830184614eb7565b9998505050505050505050565b60008060008060808587031215615784576157836148c2565b5b6000615792878288016154e9565b94505060206157a3878288016154e9565b93505060406157b4878288016152a1565b92505060606157c5878288016152a1565b91505092959194509250565b60006157dc82614925565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361580e5761580d6153c5565b5b600182019050919050565b60006101208201905061582f600083018c61488e565b61583c602083018b61488e565b615849604083018a61488e565b6158566060830189614eb7565b6158636080830188614eb7565b61587060a0830187614eb7565b61587d60c0830186614eb7565b61588a60e0830185614eb7565b615898610100830184614eb7565b9a9950505050505050505050565b60006158b182614925565b91506158bc83614925565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156158f5576158f46153c5565b5b828202905092915050565b600060c082019050615915600083018961488e565b615922602083018861488e565b61592f6040830187614eb7565b61593c606083018661488e565b6159496080830185614eb7565b61595660a0830184614eb7565b979650505050505050565b600060208284031215615977576159766148c2565b5b6000615985848285016152a1565b91505092915050565b60006060820190506159a3600083018661488e565b6159b0602083018561488e565b6159bd6040830184614eb7565b949350505050565b600080604083850312156159dc576159db6148c2565b5b60006159ea858286016154e9565b92505060206159fb858286016152a1565b9150509250929050565b6000608082019050615a1a600083018761488e565b615a276020830186614eb7565b615a34604083018561488e565b615a416060830184614eb7565b95945050505050565b6000604082019050615a5f600083018561488e565b615a6c6020830184614eb7565b9392505050565b615a7c81614e81565b8114615a8757600080fd5b50565b600081519050615a9981615a73565b92915050565b600060208284031215615ab557615ab46148c2565b5b6000615ac384828501615a8a565b9150509291505056fea2646970667358221220852d90053938a34348c1551b72abbab87a89cea070585ffb423c8713c95e529364736f6c63430008100033