Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- TwoBearsOrders
- Optimization enabled
- false
- Compiler version
- v0.8.16+commit.07a7930e
- EVM Version
- default
- Verified at
- 2024-09-26T15:35:24.109390Z
Contract source code
// All rights reserved.
// SPDX-License-Identifier: No License (None)
pragma solidity ^0.8.16;
interface IContractDeposits {
function withdraw(address _token, address _owner, uint _value) external;
function withdrawFee(address _token, uint _value) external;
}
contract TwoBearsOrders {
struct Orders {
uint256 time; // время обновляется при изменении статуса ордер
uint256 commission; // комиссия биржи за исполнение данного ордера, выплачивается в момент исполнения ордера получаемым токеном
uint256 value_in; // количество которое отдает владелец ордера (остаток обмена) (когда это значение дойдет до 0, ордер будет закрыт)
uint256 price; // цена исполнения ордера
uint256 value_out; // количество которое должен получить владелец ордера (остаток к получению) (когда это значение дойдет до 0, ордер будет закрыт)
uint256 exec_in; // количество уже обменено
uint256 exec_out; // количество уже получено
address token_in; // адрес токена который отдает владелец ордера
address token_out; // адрес токена который получает владелец ордера
address owner; // адрес владельца ордера
uint8 order_type; // тип ордера. 1 - продажа, 2 - покупка
uint8 order_status; // стутус ордера. 1 - ордер создан. 4 - ордер отменен. 6 - ордер частично выполнен. 7 - ордер закрыт (полное выполнение). 8 - помечен пользователем для удаления из системы. 9 - ордер закрыт (полное выполнение), закрыт по причине достижения лимита исполняемых ордеров, остаток меняемого токена владельцу разблокирован.
}
struct OwnerListID{
uint256 next; // указатель на следующий id ордера
uint256 prev; // указатель на предыдущий id ордера
}
struct OrderBook{
uint256 price; // цена ордера
uint256 next; // указатель на следующий id ордера
uint256 prev; // указатель на предыдущий id ордера
}
struct Variables { // структура переменных для исполнения ордера (обходим ошибку глубину стека)
uint _hash_pair;
uint _opposite_id;
uint _opposite_price;
uint _opposite_value_out;
uint _val_in_diff;
uint _temp;
uint _commission;
uint _value_add;
uint _fee_in;
uint _fee_out;
address _recipient;
}
uint256 public id; // уникальный идентификатор ордера
mapping(uint256 => mapping(uint256 => OrderBook)) private order_book; // упорядоченный список ордеров по ценам (первый параметр это хэш двух токенов без сортировки)
mapping(address => mapping(uint256 => OwnerListID)) private all_open_order; // список всех открытых ордеров владельца
mapping(uint256 => mapping(uint256 => OwnerListID)) private open_order; // открытые ордера трейдера по парам
mapping(uint256 => mapping(uint256 => OwnerListID)) private close_order; // закрытые ордера трейдера по парам
mapping(uint256 => uint256[51]) private exec_order_book; // выполненые/частично выполненые ордера на бирже. Цикличный буфер через массив, 0 - элемент указывает на текущую позицию. (первый параметр это хэш двух токенов с сортировкой)
mapping(uint256 => Orders) private orders; // все ордера на бирже
address public owner = 0xeBE894814554c8382EA6a24CcDdf1527407A24f6; // Владелец
address public constant contractDeposits = 0x275069215717568faaa7Ea54d0d5C03dBCfBD7D2; // Контракт с депозитами
event CreateOrder(uint indexed ID);
event CancelOrder(uint indexed ID);
event DeleteOrder(uint indexed ID);
event ExecutableOrder(uint indexed ID);
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this.");
_;
}
// ФУНКЦИИ ХЭШИРОВАНИЯ АДРЕСОВ
function hash2Address(address _a1, address _a2, bool _sort) private pure returns (uint256) // Возвращаем хэш по 2-м адресам, при неодходимости первоначально сортируем их
{
if(_sort){
(_a1, _a2) = _a1 < _a2 ? (_a1, _a2) : (_a2, _a1); // сортируем токены
}
return (uint256(keccak256(abi.encodePacked(_a1, _a2))));
}
function hash3Address(address _a1, address _a2, address _a3) private pure returns (uint256) // Возвращаем хэш по 3-м адресам
{
uint256 _hash = hash2Address(_a1, _a2, true); // получаем хэш первых 2-х токенов с их обязательной сортировкой
return (uint256(keccak256(abi.encodePacked(_hash, _a3))));
}
// ***************************
// ФУНКЦИИ ДЛЯ РАБОТЫ С ОРДЕРАМИ
function createOrder(address _owner, address _token_in, uint _value_in, address _token_out, uint _value_out, uint8 _order_type, uint _price, uint _order_position, uint _dex_fee, uint _dex_num_exec_ord) external returns (uint256) // создание ордера (возвращаем ID ордера)
{
require(msg.sender == contractDeposits); // Только контракт депозитов имеет право на создание ордеров
Orders memory _ord;
_ord.time = block.timestamp;
//_ord.commission = _value_in * commission / (100 * 1e18); // комиссия биржи во входящем токене
_ord.value_in = _value_in;
_ord.value_out = _value_out;
//_ord.exec_in = 0;
//_ord.exec_out = 0;
_ord.order_type = _order_type;
_ord.price = _price;
_ord.token_in = _token_in;
_ord.token_out = _token_out;
_ord.owner = _owner;
_ord.order_status = 1;
++id; // ID нового ордера
uint _id = id;
// Найдем позицию нового ордера в стакане, а также определим является ли новый ордер вершиной стакана
bool top;
(_order_position, top) = searchPositionInOrderBook(hash2Address(_token_in, _token_out, false), _order_position, _price, _order_type);
if(top){ // новый ордер размещается на вершине стакана, надо проверить возможность его исполнения
Variables memory variable;
variable._hash_pair = hash2Address(_token_out, _token_in, false); // получаем хэш по выходящему и входящему токену
variable._opposite_id = order_book[variable._hash_pair][0].prev; // вершина противоположного стакана
while(variable._opposite_id > 0){ // перебираем подходящие встречные ордера с вершины стакана в глубину
variable._opposite_price = order_book[variable._hash_pair][variable._opposite_id].price; // получаем цену ордера
if(_order_type == 1){ // новый ордер продажи
if(_price > variable._opposite_price) break; // если нет пересекающийся цены ордеров, то выполнять нечего
}
else{ // новый ордер покупки
if(_price < variable._opposite_price) break; // если нет пересекающийся цены ордеров, то выполнять нечего
}
// Контролируем лимит исполняемых ордеров
if(_dex_num_exec_ord == 0){ // если было исполнено максимальное количество ордеров установленное биржей
_ord.order_status = 9;
IContractDeposits(contractDeposits).withdraw(_token_in, _ord.owner, _ord.value_in); // не исполненый остаток от ордера возвращаем владельцу
break;
}
--_dex_num_exec_ord;
// выполняем ордера
variable._opposite_value_out = orders[variable._opposite_id].value_out; // получаем значение выходящего токена из книги ордеров
variable._val_in_diff = _ord.value_in < variable._opposite_value_out ? _ord.value_in : variable._opposite_value_out; // найдем объем входящего токена, у создающегося ордере, который надо исполнить
_ord.value_out = (_ord.value_in - variable._val_in_diff) * _ord.value_out / _ord.value_in; // остаток получения в создаваемом ордере
variable._temp = _ord.value_out == 0 ? _ord.value_in : variable._val_in_diff; // если остаток получения = 0, тогда отдаем весь вход с пылью (фактически отдает трейдер, создающий ордер)
_ord.value_in -= variable._temp; // осталось на обмен в создаваемом ордере
_ord.exec_in += variable._temp; // фактически обменяно от всего ордера
variable._commission = variable._temp * _dex_fee / (100 * 1e18); // фактически отдает ордер из книги, комиссию бирже
variable._fee_in += variable._commission; // накапливаем выплату комиссии биржи
variable._recipient = orders[variable._opposite_id].owner; // владелец чей ордер исполняется (из книги ордеров)
IContractDeposits(contractDeposits).withdraw(_token_in, variable._recipient, variable._temp - variable._commission);
orders[variable._opposite_id].exec_out += (variable._temp - variable._commission);
orders[variable._opposite_id].commission += variable._commission;
variable._temp = variable._val_in_diff * orders[variable._opposite_id].value_in / variable._opposite_value_out; // фактически отдает трейдер из книги ордеров
variable._commission = variable._temp * _dex_fee / (100 * 1e18); // фактически отдает трейдер комиссию бирже
orders[variable._opposite_id].value_in -= variable._temp; // осталось на обмен в ордере
orders[variable._opposite_id].value_out = variable._opposite_value_out - variable._val_in_diff; // осталось на обмен в ордере
orders[variable._opposite_id].exec_in += variable._temp; // фактически обменяно от всего ордера
variable._fee_out += variable._commission; // накапливаем выплату комиссии биржи
variable._value_add += (variable._temp - variable._commission);
_ord.exec_out += (variable._temp - variable._commission);
_ord.commission += variable._commission;
orders[variable._opposite_id].time = block.timestamp; // обновляем время последнего исполнения
// перекрестные ордера отработали
emit ExecutableOrder(variable._opposite_id);
if(orders[variable._opposite_id].value_in == 0){ // ордер из книги ордеров полностью отработал
orders[variable._opposite_id].order_status = 7; // статус закрытого ордера (полностью отработал)
del_ID_order_book(variable._hash_pair, variable._opposite_id); // удаляем ордер из книги ордеров
del_ID_open_order(_token_out, _token_in, variable._recipient, variable._opposite_id); // удаляем ордер в открытых ордерах
add_ID_close_order(_token_out, _token_in, variable._recipient, variable._opposite_id); // Добавить ордер в закрытые ордера
add_ID_exec_order_book(_token_out, _token_in, variable._opposite_id); // Добавляем в исполненые
variable._opposite_id = order_book[variable._hash_pair][0].prev;
}
else{ // ордер отработал частично
orders[variable._opposite_id].order_status = 6; // ордер выполнен частично
}
if(_ord.value_in == 0){ // создаваемый ордер полностью отработал
_ord.order_status = 7;
break;
}
else{
_ord.order_status = 6; // создаваемый ордер отработал частично
}
}
// Переводы создателю ордера
if(variable._value_add > 0) IContractDeposits(contractDeposits).withdraw(_token_out, _ord.owner, variable._value_add); // создатель ордера должен получить второй токен
// переводим всю собранную комиссию (комиссия копится в контракте комиссий)
if(variable._fee_in > 0) IContractDeposits(contractDeposits).withdrawFee(_token_in, variable._fee_in);
if(variable._fee_out > 0) IContractDeposits(contractDeposits).withdrawFee(_token_out, variable._fee_out);
}
orders[_id] = _ord; // сохраняем ордер целиком под уникальным номером
if ((_ord.order_status == 1) || (_ord.order_status == 6)) { // создание ордера или частичное исполнение
add_ID_order_book(hash2Address(_token_in, _token_out, false), _order_position, _id, _price); // Добавляем новый ордер в книгу ордеров
add_ID_open_order(_token_in, _token_out, _ord.owner, _id); // добавление нового ордера в открытые ордера трейдера
} else { // 7 - ордер полностью исполнен или 9 - ордер полностью исполнен (с разблокировкой оставщейся необменяной суммой)
add_ID_close_order(_token_in, _token_out, _ord.owner, _id); // добавление нового ордера в закрытые ордера трейдера
add_ID_exec_order_book(_token_in, _token_out, _id);
}
emit CreateOrder(_id);
return _id;
}
function add_ID_order_book(uint256 _hash_pair, uint _id_prev, uint _id_new, uint _price) private { // добавление нового ордера в книгу ордеров
uint _id_next = order_book[_hash_pair][_id_prev].next; // _id_new будет расположен между _id_prev и _id_next
order_book[_hash_pair][_id_prev].next = _id_new;
order_book[_hash_pair][_id_next].prev = _id_new;
order_book[_hash_pair][_id_new] = OrderBook(_price, _id_next, _id_prev);
}
function add_ID_open_order(address _token1, address _token2, address _owner, uint _id_new) private { // добавление нового ордера в открытые ордера трейдера
uint _id_last = all_open_order[_owner][0].prev; // получаем последний открытый ордер трейдера
all_open_order[_owner][_id_last].next = _id_new;
all_open_order[_owner][0].prev = _id_new;
all_open_order[_owner][_id_new].prev = _id_last; // более оптимальная запись, так как next последнего элемента всегда указывает на 0
uint256 _hash_pair_owner = hash3Address(_token1, _token2, _owner); // _hash_pair_owner - при получении хэша пары, токены были отсортированы
_id_last = open_order[_hash_pair_owner][0].prev; // получаем последний открытый ордер трейдера
open_order[_hash_pair_owner][_id_last].next = _id_new;
open_order[_hash_pair_owner][0].prev = _id_new;
open_order[_hash_pair_owner][_id_new].prev = _id_last; // более оптимальная запись, так как next последнего элемента всегда указывает на 0
}
function add_ID_close_order(address _token1, address _token2, address _owner, uint _id_new) private { // добавление нового ордера в закрытые ордера трейдера
uint256 _hash_pair_owner = hash3Address(_token1, _token2, _owner); // _hash_pair_owner - при получении хэша пары, токены были отсортированы
uint _id_last = close_order[_hash_pair_owner][0].prev; // получаем последний закрытый ордер трейдера
close_order[_hash_pair_owner][_id_last].next = _id_new;
close_order[_hash_pair_owner][0].prev = _id_new;
close_order[_hash_pair_owner][_id_new].prev = _id_last; // более оптимальная запись, так как next последнего элемента всегда указывает на 0
}
function add_ID_exec_order_book(address _token1, address _token2, uint _id_new) private { // добавление ордера в список исполненых ордеров
uint256 _hash_pair = hash2Address(_token1, _token2, true); // _hash_pair - при получении хэша пары, токены были отсортированы
uint _index = exec_order_book[_hash_pair][0]; // получаем последний элемент цикличного буфера
if(_index == 50) _index = 0; // если текущий элемент это последний элемент списка
++_index;
exec_order_book[_hash_pair][_index] = _id_new; // добавляем выполненый ордер
exec_order_book[_hash_pair][0] = _index; // запоминаем индекс последнего добавленного ордера
}
function del_ID_order_book(uint256 _hash_pair, uint _id_del) private { // удаление ордера из книги ордеров
uint _id_next = order_book[_hash_pair][_id_del].next;
uint _id_prev = order_book[_hash_pair][_id_del].prev;
order_book[_hash_pair][_id_prev].next = _id_next;
order_book[_hash_pair][_id_next].prev = _id_prev;
delete order_book[_hash_pair][_id_del];
}
function del_ID_open_order(address _token1, address _token2, address _owner, uint _id_del) private { // удаление ордера из открытых ордеров трейдера
uint _id_next = all_open_order[_owner][_id_del].next;
uint _id_prev = all_open_order[_owner][_id_del].prev;
all_open_order[_owner][_id_prev].next = _id_next;
all_open_order[_owner][_id_next].prev = _id_prev;
delete all_open_order[_owner][_id_del];
uint256 _hash_pair_owner = hash3Address(_token1, _token2, _owner); // _hash_pair_owner - при получении хэша пары, токены были отсортированы
_id_next = open_order[_hash_pair_owner][_id_del].next;
_id_prev = open_order[_hash_pair_owner][_id_del].prev;
open_order[_hash_pair_owner][_id_prev].next = _id_next;
open_order[_hash_pair_owner][_id_next].prev = _id_prev;
delete open_order[_hash_pair_owner][_id_del];
}
function del_ID_close_order(uint256 _hash_pair_owner, uint _id_del) private { // удаление ордера из закрытых ордеров трейдера
// сортировка токенов была выполнена в функции deleteCloseOrders
uint _id_next = close_order[_hash_pair_owner][_id_del].next;
uint _id_prev = close_order[_hash_pair_owner][_id_del].prev;
close_order[_hash_pair_owner][_id_prev].next = _id_next;
close_order[_hash_pair_owner][_id_next].prev = _id_prev;
delete close_order[_hash_pair_owner][_id_del];
}
function cancelOrders(uint[] memory _id_arr) external returns (uint [] memory) { // отмена ордеров, возвращаем массив с отмененными ордерами (если ордер не был отменен, то вместо его ID в массив записывается 0)
uint8 _status; // текущий статус ордера из массива
uint256 _id; // ID текущего ордера
uint _pay; // Вернуть владельцу оставшиеся токены
address _token_in;
address _token_out;
for(uint i; i < _id_arr.length; i++){ // перебираем весь массив с ордерами на отмену
_id = _id_arr[i];
_status = orders[_id].order_status;
if((orders[_id].owner == msg.sender) && ((_status == 1) || (_status == 6))){
_pay = orders[_id].value_in; // Вернуть владельцу оставшиеся токены
_token_in = orders[_id].token_in;
_token_out = orders[_id].token_out;
IContractDeposits(contractDeposits).withdraw(_token_in, msg.sender, _pay);
orders[_id].time = block.timestamp;
orders[_id].value_in = 0;
orders[_id].value_out = 0;
orders[_id].order_status = 4;
del_ID_order_book(hash2Address(_token_in, _token_out, false), _id); // удаляем ордер из книги ордеров
del_ID_open_order(_token_in, _token_out, msg.sender, _id); // удаляем ордер в открытых ордерах
add_ID_close_order(_token_in, _token_out, msg.sender, _id); // Добавить ордер в закрытые ордера
emit CancelOrder(_id);
}
else{ // ордер не может быть отменен (другой владелец или не подходящий статус ордера)
_id_arr[i] = 0; // убираем ID ордера из массива отменяемых ордеров
}
}
return (_id_arr);
}
function deleteCloseOrders(uint[] memory _id_arr) external returns (uint [] memory) { // удаление закрытых пользовательских ордеров, возвращаем массив с удаленными ордерами (если ордер не был удален, то вместо его ID в массив записывается 0)
uint8 _status; // текущий статус ордера из массива
uint256 _id; // ID текущего ордера
for(uint i; i < _id_arr.length; i++){ // перебираем весь массив с ордерами на удаление
_id = _id_arr[i];
_status = orders[_id].order_status;
if((orders[_id].owner == msg.sender) && ((_status == 4) || (_status == 7) || (_status == 9))){
del_ID_close_order(hash3Address(orders[_id].token_in, orders[_id].token_out, msg.sender), _id); // удаляем ордер из списка закрытых ордеров пользователя
orders[_id].order_status = 8; // глобально помечаем ордер для удаления из системы
emit DeleteOrder(_id);
}
else{ // ордер не может быть удален (другой владелец или не подходящий статус ордера)
_id_arr[i] = 0; // убираем ID ордера из массива удаляемых ордеров
}
}
return (_id_arr);
}
function deleteGlobalOrders(uint[] calldata _id_arr) external onlyOwner // Удаление списка ордеров из системы. Только тех ордеров, что пользователи пометили как удаляемые
{
for(uint i; i < _id_arr.length; i++){ // перебираем весь массив с ордерами на удаление
if(orders[_id_arr[i]].order_status == 8){ // можно удалять только если пользователь отметил данный ордер как удаляемый
delete orders[_id_arr[i]];
}
}
}
function searchPositionInOrderBook(uint256 _hash_pair, uint _startID, uint _price, uint8 _order_type) private view returns (uint256, bool) // вернуть ID ордера после которого будет размещен новый ордер, а также вернуть true если новый ордер это вершина стакана
{
uint256 tek_price;
uint256 next_id;
_startID = order_book[_hash_pair][_startID].price > 0 ? _startID : order_book[_hash_pair][0].prev; // определяем стартовую позицию ордера, если такого ордера нет в книге, то стартавая позиция это последний ордер в книге
tek_price = order_book[_hash_pair][_startID].price;
if(tek_price == 0){ // если книга ордеров пуста
return (0, true);
}
else{ // надо искать позицию
if(_order_type == 1){ // новый ордер продажи
if(_price < tek_price){ // поиск к вершине стакана
next_id = order_book[_hash_pair][_startID].next;
while(_price < tek_price){
if(next_id == 0) return (_startID, true);
_startID = next_id;
tek_price = order_book[_hash_pair][_startID].price;
next_id = order_book[_hash_pair][_startID].next;
}
return (order_book[_hash_pair][_startID].prev, false);
}
else{ // поиск в глубь стакана
next_id = order_book[_hash_pair][_startID].prev;
while(_price >= tek_price){
if(next_id == 0) return (0, false);
_startID = next_id;
tek_price = order_book[_hash_pair][_startID].price;
next_id = order_book[_hash_pair][_startID].prev;
}
return (_startID, false);
}
}
else{ // новый ордер покупки
if(_price > tek_price){ // поиск к вершине стакана
next_id = order_book[_hash_pair][_startID].next;
while(_price > tek_price){
if(next_id == 0) return (_startID, true);
_startID = next_id;
tek_price = order_book[_hash_pair][_startID].price;
next_id = order_book[_hash_pair][_startID].next;
}
return (order_book[_hash_pair][_startID].prev, false);
}
else{ // поиск в глубь стакана
next_id = order_book[_hash_pair][_startID].prev;
while(_price <= tek_price){
if(next_id == 0) return (0, false);
_startID = next_id;
tek_price = order_book[_hash_pair][_startID].price;
next_id = order_book[_hash_pair][_startID].prev;
}
return (_startID, false);
}
}
}
}
function get_ID_and_Prices_from_OrderBook(address _token_in, address _token_out, uint _id_start, uint _amount) public view returns (uint [] memory) // Возвращает ID и цены из книги ордеров (для фронта). Фронт учавствует в поиске позиции для ордера
{
uint256 _hash_pair = hash2Address(_token_in, _token_out, false); // получаем хэш пары по входящему и выходящему токену
_id_start = order_book[_hash_pair][_id_start].price > 0 ? _id_start : order_book[_hash_pair][0].prev; // определяем стартовую позицию ордера, если такого ордера нет в книге, то стартавая позиция это последний ордер в книге
uint _index;
uint[] memory result = new uint[](_amount * 2); // [ID, цена...]
for(uint i; i < _amount; i++){
if(_id_start == 0) break;
result[_index++] = _id_start;
result[_index++] = order_book[_hash_pair][_id_start].price;
_id_start = order_book[_hash_pair][_id_start].prev;
}
return (result);
}
function getOrderByID(uint _id) public view returns (Orders memory) // Возвращаем ордер по ID
{
return (orders[_id]);
}
function getOrderBook(address _token_in, address _token_out, uint _amount) public view returns (uint [] memory) // Возвращаем ордера стакана от вершины стакана в глубину
{
uint256 _hash_pair = hash2Address(_token_in, _token_out, false); // получаем хэш пары по входящему и выходящему токену
uint _index;
uint _id = order_book[_hash_pair][0].prev;
uint[] memory result = new uint[](_amount * 3); // [цена, отдаю, получаю...]
for(uint i; i < _amount; i++){
if(_id == 0) break;
result[_index++] = orders[_id].price;
result[_index++] = orders[_id].value_in;
result[_index++] = orders[_id].value_out;
_id = order_book[_hash_pair][_id].prev;
}
return (result);
}
function getExecOrderBook(address _token1, address _token2) public view returns (uint [] memory) // Возвращаем выполненые ордера в данной торговой паре
{
uint256 _hash_pair = hash2Address(_token1, _token2, true); // _hash_pair - при получении хэша пары, токены были отсортированы
uint _index_top = exec_order_book[_hash_pair][0];
if(_index_top == 0) return (new uint[](1)); // если исполненых ордеров еще не существует, вернем [0]
uint _index;
uint _id;
uint[] memory result = new uint[](50 * 6); // [id, тип_ордера, время, цена, отдал, получил...]
for(uint i = 0; i < 50; i++){
_id = exec_order_book[_hash_pair][_index_top];
result[_index++] = _id;
result[_index++] = orders[_id].order_type;
result[_index++] = orders[_id].time;
result[_index++] = orders[_id].price;
result[_index++] = orders[_id].exec_in;
result[_index++] = orders[_id].exec_out;
if(--_index_top == 0){
_index_top = 50;
if(exec_order_book[_hash_pair][_index_top] == 0) break; // обрываем цикл если исполнено менее 50 ордеров
}
}
return (result);
}
function getAllOpenOrders(address _owner, uint _id, uint _amount) public view returns (uint [] memory) // Возвращаем указанное количество открытых ордеров пользователя, со сдедующего ордера от стартового ID
{ // если _id = 0, тогда открытые ордера формируются с самого последнего ордера
_id = all_open_order[_owner][_id].prev;
if(_id == 0) return (new uint[](1)); // если открытых ордеров еще не существует, либо если это первый ордер в списке, который уже был обработан, вернем [0]
uint _index;
uint[] memory result = new uint[](_amount * 9); // [id, время, цена, осталось_отдать, адрес_токена_IN, осталось_получить, адрес_токена_OUT, тип_ордера, статус...]
for(uint i; i < _amount; i++){
if(_id == 0) break;
result[_index++] = _id;
result[_index++] = orders[_id].time;
result[_index++] = orders[_id].price;
result[_index++] = orders[_id].value_in;
result[_index++] = uint256(uint160(orders[_id].token_in));
result[_index++] = orders[_id].value_out;
result[_index++] = uint256(uint160(orders[_id].token_out));
result[_index++] = orders[_id].order_type;
result[_index++] = orders[_id].order_status;
_id = all_open_order[_owner][_id].prev;
}
return (result);
}
function getOpenOrders(address _token1, address _token2, address _owner, uint _id, uint _amount) public view returns (uint [] memory) // Возвращаем указанное количество открытых ордеров пользователя, со сдедующего ордера от стартового ID, в данной торговой паре
{ // если _id = 0, тогда открытые ордера формируются с самого последнего ордера
uint256 _hash_pair_owner = hash3Address(_token1, _token2, _owner); // _hash_pair_owner - при получении хэша пары, токены были отсортированы
_id = open_order[_hash_pair_owner][_id].prev;
if(_id == 0) return (new uint[](1)); // если открытых ордеров еще не существует, либо если это первый ордер в списке, который уже был обработан, вернем [0]
uint _index;
uint[] memory result = new uint[](_amount * 6); // [id, тип_ордера, время, цена, осталось_отдать, осталось_получить...]
for(uint i; i < _amount; i++){
if(_id == 0) break;
result[_index++] = _id;
result[_index++] = orders[_id].order_type;
result[_index++] = orders[_id].time;
result[_index++] = orders[_id].price;
result[_index++] = orders[_id].value_in;
result[_index++] = orders[_id].value_out;
_id = open_order[_hash_pair_owner][_id].prev;
}
return (result);
}
function getCloseOrders(address _token1, address _token2, address _owner, uint _id, uint _amount) public view returns (uint [] memory) // Возвращаем указанное количество закрытых ордеров пользователя, со следующего ордера от стартового ID, в данной торговой паре
{ // если _id = 0, тогда закрытые ордера формируются с самого последнего ордера
uint256 _hash_pair_owner = hash3Address(_token1, _token2, _owner); // _hash_pair_owner - при получении хэша пары, токены были отсортированы
_id = close_order[_hash_pair_owner][_id].prev;
if(_id == 0) return (new uint[](1)); // если закрытых ордеров еще не существует, либо если это первый ордер в списке, который уже был обработан, вернем [0]
uint _index;
uint[] memory result = new uint[](_amount * 6); // [id, тип_ордера, время, цена, отдал, получил...]
for(uint i; i < _amount; i++){
if(_id == 0) break;
result[_index++] = _id;
result[_index++] = orders[_id].order_type;
result[_index++] = orders[_id].time;
result[_index++] = orders[_id].price;
result[_index++] = orders[_id].exec_in;
result[_index++] = orders[_id].exec_out;
_id = close_order[_hash_pair_owner][_id].prev;
}
return (result);
}
// Функции для работы с ботами
function getOrderDataForOracle(uint _id) public view returns (uint [] memory) // Возвращаем данные по ордеру необходимые оракулу
{
uint[] memory result = new uint[](6); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил]
result[0] = orders[_id].order_status;
result[1] = orders[_id].order_type;
result[2] = orders[_id].value_in;
result[3] = orders[_id].value_out;
result[4] = orders[_id].exec_in;
result[5] = orders[_id].exec_out;
return (result);
}
function getCloseOrdersOracle(address _token1, address _token2, address _owner, uint _id, uint _amount) public view returns (uint [] memory) // Возвращаем указанное количество ID закрытых ордеров пользователя, со следующего ордера от стартового ID, в данной торговой паре
{ // если _id = 0, тогда закрытые ордера формируются с самого последнего ордера
uint256 _hash_pair_owner = hash3Address(_token1, _token2, _owner); // _hash_pair_owner - при получении хэша пары, токены были отсортированы
_id = close_order[_hash_pair_owner][_id].prev;
if(_id == 0) return (new uint[](1)); // если закрытых ордеров еще не существует, либо если это первый ордер в списке, который уже был обработан, вернем [0]
uint _index;
uint[] memory result = new uint[](_amount); // [id,...]
for(uint i; i < _amount; i++){
if(_id == 0) break;
result[_index++] = _id;
_id = close_order[_hash_pair_owner][_id].prev;
}
return (result);
}
}
Contract ABI
[{"type":"event","name":"CancelOrder","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"CreateOrder","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"DeleteOrder","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutableOrder","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"cancelOrders","inputs":[{"type":"uint256[]","name":"_id_arr","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractDeposits","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"createOrder","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"address","name":"_token_in","internalType":"address"},{"type":"uint256","name":"_value_in","internalType":"uint256"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_value_out","internalType":"uint256"},{"type":"uint8","name":"_order_type","internalType":"uint8"},{"type":"uint256","name":"_price","internalType":"uint256"},{"type":"uint256","name":"_order_position","internalType":"uint256"},{"type":"uint256","name":"_dex_fee","internalType":"uint256"},{"type":"uint256","name":"_dex_num_exec_ord","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"deleteCloseOrders","inputs":[{"type":"uint256[]","name":"_id_arr","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteGlobalOrders","inputs":[{"type":"uint256[]","name":"_id_arr","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getAllOpenOrders","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getCloseOrders","inputs":[{"type":"address","name":"_token1","internalType":"address"},{"type":"address","name":"_token2","internalType":"address"},{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getCloseOrdersOracle","inputs":[{"type":"address","name":"_token1","internalType":"address"},{"type":"address","name":"_token2","internalType":"address"},{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getExecOrderBook","inputs":[{"type":"address","name":"_token1","internalType":"address"},{"type":"address","name":"_token2","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getOpenOrders","inputs":[{"type":"address","name":"_token1","internalType":"address"},{"type":"address","name":"_token2","internalType":"address"},{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getOrderBook","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TwoBearsOrders.Orders","components":[{"type":"uint256","name":"time","internalType":"uint256"},{"type":"uint256","name":"commission","internalType":"uint256"},{"type":"uint256","name":"value_in","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"value_out","internalType":"uint256"},{"type":"uint256","name":"exec_in","internalType":"uint256"},{"type":"uint256","name":"exec_out","internalType":"uint256"},{"type":"address","name":"token_in","internalType":"address"},{"type":"address","name":"token_out","internalType":"address"},{"type":"address","name":"owner","internalType":"address"},{"type":"uint8","name":"order_type","internalType":"uint8"},{"type":"uint8","name":"order_status","internalType":"uint8"}]}],"name":"getOrderByID","inputs":[{"type":"uint256","name":"_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getOrderDataForOracle","inputs":[{"type":"uint256","name":"_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"get_ID_and_Prices_from_OrderBook","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_id_start","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"id","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]}]
Contract Creation Code
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50614886806100756000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806375b02405116100975780639435298b116100665780639435298b1461030d578063af640d0f1461033d578063b55fb5741461035b578063e0a313391461038b57610100565b806375b024051461025f5780637e9da7a21461028f578063809741ed146102bf5780638da5cb5b146102ef57610100565b8063334503bf116100d3578063334503bf1461019f57806347402bea146101cf5780635eb2088e146101ff5780636da42a151461022f57610100565b80630e0578f514610105578063127e11971461013557806318df238814610153578063299821f614610183575b600080fd5b61011f600480360381019061011a9190613ca8565b6103bb565b60405161012c9190613e37565b60405180910390f35b61013d61056b565b60405161014a9190613e62565b60405180910390f35b61016d60048036038101906101689190613ea9565b610583565b60405161017a9190613fbf565b60405180910390f35b61019d60048036038101906101989190614046565b61072e565b005b6101b960048036038101906101b49190614093565b610930565b6040516101c69190613fbf565b60405180910390f35b6101e960048036038101906101e4919061413a565b610c07565b6040516101f69190614228565b60405180910390f35b61021960048036038101906102149190614243565b6118f1565b6040516102269190613fbf565b60405180910390f35b61024960048036038101906102449190613ca8565b611d4f565b6040516102569190613fbf565b60405180910390f35b610279600480360381019061027491906143e5565b611f12565b6040516102869190613fbf565b60405180910390f35b6102a960048036038101906102a49190614093565b61211d565b6040516102b69190613fbf565b60405180910390f35b6102d960048036038101906102d4919061442e565b6123f4565b6040516102e69190613fbf565b60405180910390f35b6102f7612705565b6040516103049190613e62565b60405180910390f35b6103276004803603810190610322919061446e565b61272b565b6040516103349190613fbf565b60405180910390f35b6103456128e9565b6040516103529190614228565b60405180910390f35b610375600480360381019061037091906143e5565b6128ef565b6040516103829190613fbf565b60405180910390f35b6103a560048036038101906103a09190614093565b612c01565b6040516103b29190613fbf565b60405180910390f35b6103c3613b45565b6006600083815260200190815260200160002060405180610180016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016008820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160149054906101000a900460ff1660ff1660ff1681526020016009820160159054906101000a900460ff1660ff1660ff16815250509050919050565b73275069215717568faaa7ea54d0d5c03dbcfbd7d281565b6060600061059386866000612d72565b9050600060016000838152602001908152602001600020600086815260200190815260200160002060000154116105f157600160008281526020019081526020016000206000808152602001908152602001600020600201546105f3565b835b935060008060028561060591906144f0565b67ffffffffffffffff81111561061e5761061d6142a7565b5b60405190808252806020026020018201604052801561064c5781602001602082028036833780820191505090505b50905060005b8581101561071f57600087031561071f57868284806106709061454a565b95508151811061068357610682614592565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600001548284806106c39061454a565b9550815181106106d6576106d5614592565b5b60200260200101818152505060016000858152602001908152602001600020600088815260200190815260200160002060020154965080806107179061454a565b915050610652565b50809350505050949350505050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b59061461e565b60405180910390fd5b60005b8282905081101561092b576008600660008585858181106107e5576107e4614592565b5b90506020020135815260200190815260200160002060090160159054906101000a900460ff1660ff1603610918576006600084848481811061082a57610829614592565b5b9050602002013581526020019081526020016000206000808201600090556001820160009055600282016000905560038201600090556004820160009055600582016000905560068201600090556007820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160146101000a81549060ff02191690556009820160156101000a81549060ff021916905550505b80806109239061454a565b9150506107c1565b505050565b6060600061093f878787612df5565b9050600360008281526020019081526020016000206000858152602001908152602001600020600101549350600084036109c557600167ffffffffffffffff81111561098e5761098d6142a7565b5b6040519080825280602002602001820160405280156109bc5781602001602082028036833780820191505090505b50915050610bfe565b6000806006856109d591906144f0565b67ffffffffffffffff8111156109ee576109ed6142a7565b5b604051908082528060200260200182016040528015610a1c5781602001602082028036833780820191505090505b50905060005b85811015610bf6576000870315610bf65786828480610a409061454a565b955081518110610a5357610a52614592565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff16828480610a929061454a565b955081518110610aa557610aa4614592565b5b6020026020010181815250506006600088815260200190815260200160002060000154828480610ad49061454a565b955081518110610ae757610ae6614592565b5b6020026020010181815250506006600088815260200190815260200160002060030154828480610b169061454a565b955081518110610b2957610b28614592565b5b6020026020010181815250506006600088815260200190815260200160002060020154828480610b589061454a565b955081518110610b6b57610b6a614592565b5b6020026020010181815250506006600088815260200190815260200160002060040154828480610b9a9061454a565b955081518110610bad57610bac614592565b5b6020026020010181815250506003600085815260200190815260200160002060008881526020019081526020016000206001015496508080610bee9061454a565b915050610a22565b508093505050505b95945050505050565b600073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c5557600080fd5b610c5d613b45565b4281600001818152505089816040018181525050878160800181815250508681610140019060ff16908160ff1681525050858160600181815250508a8160e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508881610100019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508b81610120019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181610160019060ff16908160ff16815250506000808154610d649061454a565b919050819055506000805490506000610d8a610d828e8d6000612d72565b888a8c612e3c565b809250819850505080156116ca57610da0613bee565b610dac8c8f6000612d72565b81600001818152505060016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250505b6000816020015111156115045760016000826000015181526020019081526020016000206000826020015181526020019081526020016000206000015481604001818152505060018a60ff1603610e4c578060400151891161150457610e58565b80604001518910611504575b60008603610f0557600984610160019060ff16908160ff168152505073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128f86610120015187604001516040518463ffffffff1660e01b8152600401610ece9392919061463e565b600060405180830381600087803b158015610ee857600080fd5b505af1158015610efc573d6000803e3d6000fd5b50505050611504565b85610f0f90614675565b95506006600082602001518152602001908152602001600020600401548160600181815250508060600151846040015110610f4e578060600151610f54565b83604001515b8160800181815250508360400151846080015182608001518660400151610f7b919061469e565b610f8591906144f0565b610f8f9190614701565b8460800181815250506000846080015114610fae578060800151610fb4565b83604001515b8160a00181815250508060a0015184604001818151610fd3919061469e565b915081815250508060a001518460a001818151610ff09190614732565b9150818152505068056bc75e2d63100000878260a0015161101191906144f0565b61101b9190614701565b8160c00181815250508060c00151816101000181815161103b9190614732565b91508181525050600660008260200151815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681610140019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128f8361014001518460c001518560a00151611100919061469e565b6040518463ffffffff1660e01b815260040161111e9392919061463e565b600060405180830381600087803b15801561113857600080fd5b505af115801561114c573d6000803e3d6000fd5b505050508060c001518160a00151611164919061469e565b6006600083602001518152602001908152602001600020600601600082825461118d9190614732565b925050819055508060c00151600660008360200151815260200190815260200160002060010160008282546111c29190614732565b92505081905550806060015160066000836020015181526020019081526020016000206002015482608001516111f891906144f0565b6112029190614701565b8160a001818152505068056bc75e2d63100000878260a0015161122591906144f0565b61122f9190614701565b8160c00181815250508060a0015160066000836020015181526020019081526020016000206002016000828254611266919061469e565b9250508190555080608001518160600151611281919061469e565b6006600083602001518152602001908152602001600020600401819055508060a00151600660008360200151815260200190815260200160002060050160008282546112cd9190614732565b925050819055508060c0015181610120018181516112eb9190614732565b915081815250508060c001518160a00151611306919061469e565b8160e0018181516113179190614732565b915081815250508060c001518160a00151611332919061469e565b8460c0018181516113439190614732565b915081815250508060c00151846020018181516113609190614732565b915081815250504260066000836020015181526020019081526020016000206000018190555080602001517f271adf7ca5026da9466c7e2ee50294432b6518106821bb0baa27adfbe5203bad60405160405180910390a2600060066000836020015181526020019081526020016000206002015403611492576007600660008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061141f8160000151826020015161321b565b6114348c8f8361014001518460200151613310565b6114498c8f83610140015184602001516135ce565b6114588c8f8360200151613695565b60016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250506114c6565b60068060008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055505b60008460400151036114eb57600784610160019060ff16908160ff1681525050611504565b600684610160019060ff16908160ff1681525050610deb565b60008160e00151111561159e5773275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128d8661012001518460e001516040518463ffffffff1660e01b815260040161156b9392919061463e565b600060405180830381600087803b15801561158557600080fd5b505af1158015611599573d6000803e3d6000fd5b505050505b600081610100015111156116335773275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663fd9be5228f8361010001516040518363ffffffff1660e01b8152600401611600929190614766565b600060405180830381600087803b15801561161a57600080fd5b505af115801561162e573d6000803e3d6000fd5b505050505b600081610120015111156116c85773275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663fd9be5228d8361012001516040518363ffffffff1660e01b8152600401611695929190614766565b600060405180830381600087803b1580156116af57600080fd5b505af11580156116c3573d6000803e3d6000fd5b505050505b505b8260066000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101008201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160090160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101408201518160090160146101000a81548160ff021916908360ff1602179055506101608201518160090160156101000a81548160ff021916908360ff160217905550905050600183610160015160ff1614806118615750600683610160015160ff16145b156118935761187d6118758e8d6000612d72565b88848b613748565b61188e8d8c85610120015185613833565b6118b0565b6118a48d8c856101200151856135ce565b6118af8d8c84613695565b5b817f2f539bcf68b0eef24f9fef1ae5ad7dd5a37f80a2fab34f406ad2b92c779d606460405160405180910390a28193505050509a9950505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101549250600083036119a257600167ffffffffffffffff81111561196c5761196b6142a7565b5b60405190808252806020026020018201604052801561199a5781602001602082028036833780820191505090505b509050611d48565b6000806009846119b291906144f0565b67ffffffffffffffff8111156119cb576119ca6142a7565b5b6040519080825280602002602001820160405280156119f95781602001602082028036833780820191505090505b50905060005b84811015611d41576000860315611d415785828480611a1d9061454a565b955081518110611a3057611a2f614592565b5b6020026020010181815250506006600087815260200190815260200160002060000154828480611a5f9061454a565b955081518110611a7257611a71614592565b5b6020026020010181815250506006600087815260200190815260200160002060030154828480611aa19061454a565b955081518110611ab457611ab3614592565b5b6020026020010181815250506006600087815260200190815260200160002060020154828480611ae39061454a565b955081518110611af657611af5614592565b5b6020026020010181815250506006600087815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16828480611b5b9061454a565b955081518110611b6e57611b6d614592565b5b6020026020010181815250506006600087815260200190815260200160002060040154828480611b9d9061454a565b955081518110611bb057611baf614592565b5b6020026020010181815250506006600087815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16828480611c159061454a565b955081518110611c2857611c27614592565b5b6020026020010181815250506006600087815260200190815260200160002060090160149054906101000a900460ff1660ff16828480611c679061454a565b955081518110611c7a57611c79614592565b5b6020026020010181815250506006600087815260200190815260200160002060090160159054906101000a900460ff1660ff16828480611cb99061454a565b955081518110611ccc57611ccb614592565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206001015495508080611d399061454a565b9150506119ff565b5080925050505b9392505050565b60606000600667ffffffffffffffff811115611d6e57611d6d6142a7565b5b604051908082528060200260200182016040528015611d9c5781602001602082028036833780820191505090505b5090506006600084815260200190815260200160002060090160159054906101000a900460ff1660ff1681600081518110611dda57611dd9614592565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff1681600181518110611e2157611e20614592565b5b602002602001018181525050600660008481526020019081526020016000206002015481600281518110611e5857611e57614592565b5b602002602001018181525050600660008481526020019081526020016000206004015481600381518110611e8f57611e8e614592565b5b602002602001018181525050600660008481526020019081526020016000206005015481600481518110611ec657611ec5614592565b5b602002602001018181525050600660008481526020019081526020016000206006015481600581518110611efd57611efc614592565b5b60200260200101818152505080915050919050565b606060008060005b845181101561211257848181518110611f3657611f35614592565b5b602002602001015191506006600083815260200190815260200160002060090160159054906101000a900460ff1692503373ffffffffffffffffffffffffffffffffffffffff166006600084815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611ff6575060048360ff161480611fe7575060078360ff16145b80611ff5575060098360ff16145b5b156120dd5761207b6120756006600085815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633612df5565b83613a58565b60086006600084815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550817fbd000546857b596b03c884060c13e7d8c7a7ce52366d2f116f76688e6f000f6660405160405180910390a26120ff565b60008582815181106120f2576120f1614592565b5b6020026020010181815250505b808061210a9061454a565b915050611f1a565b508392505050919050565b6060600061212c878787612df5565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036121b257600167ffffffffffffffff81111561217b5761217a6142a7565b5b6040519080825280602002602001820160405280156121a95781602001602082028036833780820191505090505b509150506123eb565b6000806006856121c291906144f0565b67ffffffffffffffff8111156121db576121da6142a7565b5b6040519080825280602002602001820160405280156122095781602001602082028036833780820191505090505b50905060005b858110156123e35760008703156123e3578682848061222d9061454a565b9550815181106122405761223f614592565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061227f9061454a565b95508151811061229257612291614592565b5b60200260200101818152505060066000888152602001908152602001600020600001548284806122c19061454a565b9550815181106122d4576122d3614592565b5b60200260200101818152505060066000888152602001908152602001600020600301548284806123039061454a565b95508151811061231657612315614592565b5b60200260200101818152505060066000888152602001908152602001600020600501548284806123459061454a565b95508151811061235857612357614592565b5b60200260200101818152505060066000888152602001908152602001600020600601548284806123879061454a565b95508151811061239a57612399614592565b5b60200260200101818152505060046000858152602001908152602001600020600088815260200190815260200160002060010154965080806123db9061454a565b91505061220f565b508093505050505b95945050505050565b6060600061240484846001612d72565b905060006005600083815260200190815260200160002060006033811061242e5761242d614592565b5b015490506000810361248d57600167ffffffffffffffff811115612455576124546142a7565b5b6040519080825280602002602001820160405280156124835781602001602082028036833780820191505090505b50925050506126ff565b600080600061012c67ffffffffffffffff8111156124ae576124ad6142a7565b5b6040519080825280602002602001820160405280156124dc5781602001602082028036833780820191505090505b50905060005b60328110156126f5576005600087815260200190815260200160002085603381106125105761250f614592565b5b01549250828285806125219061454a565b96508151811061253457612533614592565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff168285806125739061454a565b96508151811061258657612585614592565b5b60200260200101818152505060066000848152602001908152602001600020600001548285806125b59061454a565b9650815181106125c8576125c7614592565b5b60200260200101818152505060066000848152602001908152602001600020600301548285806125f79061454a565b96508151811061260a57612609614592565b5b60200260200101818152505060066000848152602001908152602001600020600501548285806126399061454a565b96508151811061264c5761264b614592565b5b602002602001018181525050600660008481526020019081526020016000206006015482858061267b9061454a565b96508151811061268e5761268d614592565b5b6020026020010181815250506000856126a690614675565b955085036126e2576032945060006005600088815260200190815260200160002086603381106126d9576126d8614592565b5b015403156126f5575b80806126ed9061454a565b9150506124e2565b5080955050505050505b92915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600061273b85856000612d72565b9050600080600160008481526020019081526020016000206000808152602001908152602001600020600201549050600060038661277991906144f0565b67ffffffffffffffff811115612792576127916142a7565b5b6040519080825280602002602001820160405280156127c05781602001602082028036833780820191505090505b50905060005b868110156128da5760008303156128da5760066000848152602001908152602001600020600301548285806127fa9061454a565b96508151811061280d5761280c614592565b5b602002602001018181525050600660008481526020019081526020016000206002015482858061283c9061454a565b96508151811061284f5761284e614592565b5b602002602001018181525050600660008481526020019081526020016000206004015482858061287e9061454a565b96508151811061289157612890614592565b5b60200260200101818152505060016000868152602001908152602001600020600084815260200190815260200160002060020154925080806128d29061454a565b9150506127c6565b50809450505050509392505050565b60005481565b60606000806000806000805b8751811015612bf35787818151811061291757612916614592565b5b602002602001015194506006600086815260200190815260200160002060090160159054906101000a900460ff1695503373ffffffffffffffffffffffffffffffffffffffff166006600087815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480156129c9575060018660ff1614806129c8575060068660ff16145b5b15612bbe57600660008681526020019081526020016000206002015493506006600086815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692506006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128433876040518463ffffffff1660e01b8152600401612aaa9392919061463e565b600060405180830381600087803b158015612ac457600080fd5b505af1158015612ad8573d6000803e3d6000fd5b50505050426006600087815260200190815260200160002060000181905550600060066000878152602001908152602001600020600201819055506000600660008781526020019081526020016000206004018190555060046006600087815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550612b74612b6e84846000612d72565b8661321b565b612b8083833388613310565b612b8c838333886135ce565b847f935c9ad2f1fda9d7eae0d2a512f1521cb7190ee06165414e722366a65975fb6b60405160405180910390a2612be0565b6000888281518110612bd357612bd2614592565b5b6020026020010181815250505b8080612beb9061454a565b9150506128fb565b508695505050505050919050565b60606000612c10878787612df5565b905060046000828152602001908152602001600020600085815260200190815260200160002060010154935060008403612c9657600167ffffffffffffffff811115612c5f57612c5e6142a7565b5b604051908082528060200260200182016040528015612c8d5781602001602082028036833780820191505090505b50915050612d69565b6000808467ffffffffffffffff811115612cb357612cb26142a7565b5b604051908082528060200260200182016040528015612ce15781602001602082028036833780820191505090505b50905060005b85811015612d61576000870315612d615786828480612d059061454a565b955081518110612d1857612d17614592565b5b6020026020010181815250506004600085815260200190815260200160002060008881526020019081526020016000206001015496508080612d599061454a565b915050612ce7565b508093505050505b95945050505050565b60008115612dc0578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610612db4578284612db7565b83835b80945081955050505b8383604051602001612dd39291906147d7565b6040516020818303038152906040528051906020012060001c90509392505050565b600080612e0485856001612d72565b90508083604051602001612e19929190614824565b6040516020818303038152906040528051906020012060001c9150509392505050565b6000806000806000600160008a815260200190815260200160002060008981526020019081526020016000206000015411612e9e5760016000898152602001908152602001600020600080815260200190815260200160002060020154612ea0565b865b965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060008203612ee35760006001935093505050613212565b60018560ff16036130825781861015612fd0576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b81861015612f9b5760008103612f3f57866001935093505050613212565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600101549050612f21565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613212565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b818610613074576000810361301857600080935093505050613212565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600201549050612ffb565b866000935093505050613212565b81861115613164576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b8186111561312f57600081036130d357866001935093505050613212565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206001015490506130b5565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613212565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861161320857600081036131ac57600080935093505050613212565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060020154905061318f565b8660009350935050505b94509492505050565b600060016000848152602001908152602001600020600083815260200190815260200160002060010154905060006001600085815260200190815260200160002060008481526020019081526020016000206002015490508160016000868152602001908152602001600020600083815260200190815260200160002060010181905550806001600086815260200190815260200160002060008481526020019081526020016000206002018190555060016000858152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505060006134e0878787612df5565b9050600360008281526020019081526020016000206000858152602001908152602001600020600001549250600360008281526020019081526020016000206000858152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555081600360008381526020019081526020016000206000858152602001908152602001600020600101819055506003600082815260200190815260200160002060008581526020019081526020016000206000808201600090556001820160009055505050505050505050565b60006135db858585612df5565b90506000600460008381526020019081526020016000206000808152602001908152602001600020600101549050826004600084815260200190815260200160002060008381526020019081526020016000206000018190555082600460008481526020019081526020016000206000808152602001908152602001600020600101819055508060046000848152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006136a384846001612d72565b90506000600560008381526020019081526020016000206000603381106136cd576136cc614592565b5b01549050603281036136de57600090505b806136e89061454a565b9050826005600084815260200190815260200160002082603381106137105761370f614592565b5b0181905550806005600084815260200190815260200160002060006033811061373c5761373b614592565b5b01819055505050505050565b6000600160008681526020019081526020016000206000858152602001908152602001600020600101549050826001600087815260200190815260200160002060008681526020019081526020016000206001018190555082600160008781526020019081526020016000206000838152602001908152602001600020600201819055506040518060600160405280838152602001828152602001858152506001600087815260200190815260200160002060008581526020019081526020016000206000820151816000015560208201518160010155604082015181600201559050505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060010154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206001018190555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001018190555060006139a0868686612df5565b9050600360008281526020019081526020016000206000808152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555082600360008381526020019081526020016000206000808152602001908152602001600020600101819055508160036000838152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006004600084815260200190815260200160002060008381526020019081526020016000206000015490506000600460008581526020019081526020016000206000848152602001908152602001600020600101549050816004600086815260200190815260200160002060008381526020019081526020016000206000018190555080600460008681526020019081526020016000206000848152602001908152602001600020600101819055506004600085815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505050505050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b613c8581613c72565b8114613c9057600080fd5b50565b600081359050613ca281613c7c565b92915050565b600060208284031215613cbe57613cbd613c68565b5b6000613ccc84828501613c93565b91505092915050565b613cde81613c72565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613d0f82613ce4565b9050919050565b613d1f81613d04565b82525050565b600060ff82169050919050565b613d3b81613d25565b82525050565b61018082016000820151613d586000850182613cd5565b506020820151613d6b6020850182613cd5565b506040820151613d7e6040850182613cd5565b506060820151613d916060850182613cd5565b506080820151613da46080850182613cd5565b5060a0820151613db760a0850182613cd5565b5060c0820151613dca60c0850182613cd5565b5060e0820151613ddd60e0850182613d16565b50610100820151613df2610100850182613d16565b50610120820151613e07610120850182613d16565b50610140820151613e1c610140850182613d32565b50610160820151613e31610160850182613d32565b50505050565b600061018082019050613e4d6000830184613d41565b92915050565b613e5c81613d04565b82525050565b6000602082019050613e776000830184613e53565b92915050565b613e8681613d04565b8114613e9157600080fd5b50565b600081359050613ea381613e7d565b92915050565b60008060008060808587031215613ec357613ec2613c68565b5b6000613ed187828801613e94565b9450506020613ee287828801613e94565b9350506040613ef387828801613c93565b9250506060613f0487828801613c93565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000613f488383613cd5565b60208301905092915050565b6000602082019050919050565b6000613f6c82613f10565b613f768185613f1b565b9350613f8183613f2c565b8060005b83811015613fb2578151613f998882613f3c565b9750613fa483613f54565b925050600181019050613f85565b5085935050505092915050565b60006020820190508181036000830152613fd98184613f61565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261400657614005613fe1565b5b8235905067ffffffffffffffff81111561402357614022613fe6565b5b60208301915083602082028301111561403f5761403e613feb565b5b9250929050565b6000806020838503121561405d5761405c613c68565b5b600083013567ffffffffffffffff81111561407b5761407a613c6d565b5b61408785828601613ff0565b92509250509250929050565b600080600080600060a086880312156140af576140ae613c68565b5b60006140bd88828901613e94565b95505060206140ce88828901613e94565b94505060406140df88828901613e94565b93505060606140f088828901613c93565b925050608061410188828901613c93565b9150509295509295909350565b61411781613d25565b811461412257600080fd5b50565b6000813590506141348161410e565b92915050565b6000806000806000806000806000806101408b8d03121561415e5761415d613c68565b5b600061416c8d828e01613e94565b9a5050602061417d8d828e01613e94565b995050604061418e8d828e01613c93565b985050606061419f8d828e01613e94565b97505060806141b08d828e01613c93565b96505060a06141c18d828e01614125565b95505060c06141d28d828e01613c93565b94505060e06141e38d828e01613c93565b9350506101006141f58d828e01613c93565b9250506101206142078d828e01613c93565b9150509295989b9194979a5092959850565b61422281613c72565b82525050565b600060208201905061423d6000830184614219565b92915050565b60008060006060848603121561425c5761425b613c68565b5b600061426a86828701613e94565b935050602061427b86828701613c93565b925050604061428c86828701613c93565b9150509250925092565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6142df82614296565b810181811067ffffffffffffffff821117156142fe576142fd6142a7565b5b80604052505050565b6000614311613c5e565b905061431d82826142d6565b919050565b600067ffffffffffffffff82111561433d5761433c6142a7565b5b602082029050602081019050919050565b600061436161435c84614322565b614307565b9050808382526020820190506020840283018581111561438457614383613feb565b5b835b818110156143ad57806143998882613c93565b845260208401935050602081019050614386565b5050509392505050565b600082601f8301126143cc576143cb613fe1565b5b81356143dc84826020860161434e565b91505092915050565b6000602082840312156143fb576143fa613c68565b5b600082013567ffffffffffffffff81111561441957614418613c6d565b5b614425848285016143b7565b91505092915050565b6000806040838503121561444557614444613c68565b5b600061445385828601613e94565b925050602061446485828601613e94565b9150509250929050565b60008060006060848603121561448757614486613c68565b5b600061449586828701613e94565b93505060206144a686828701613e94565b92505060406144b786828701613c93565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006144fb82613c72565b915061450683613c72565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561453f5761453e6144c1565b5b828202905092915050565b600061455582613c72565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614587576145866144c1565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732e00000000000000600082015250565b60006146086019836145c1565b9150614613826145d2565b602082019050919050565b60006020820190508181036000830152614637816145fb565b9050919050565b60006060820190506146536000830186613e53565b6146606020830185613e53565b61466d6040830184614219565b949350505050565b600061468082613c72565b915060008203614693576146926144c1565b5b600182039050919050565b60006146a982613c72565b91506146b483613c72565b92508282039050818111156146cc576146cb6144c1565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061470c82613c72565b915061471783613c72565b925082614727576147266146d2565b5b828204905092915050565b600061473d82613c72565b915061474883613c72565b92508282019050808211156147605761475f6144c1565b5b92915050565b600060408201905061477b6000830185613e53565b6147886020830184614219565b9392505050565b60008160601b9050919050565b60006147a78261478f565b9050919050565b60006147b98261479c565b9050919050565b6147d16147cc82613d04565b6147ae565b82525050565b60006147e382856147c0565b6014820191506147f382846147c0565b6014820191508190509392505050565b6000819050919050565b61481e61481982613c72565b614803565b82525050565b6000614830828561480d565b60208201915061484082846147c0565b601482019150819050939250505056fea26469706673582212205148ac67da01a6975108de201292291b3ca6d7b06ba3a7e54c5e334bf685ce0964736f6c63430008100033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c806375b02405116100975780639435298b116100665780639435298b1461030d578063af640d0f1461033d578063b55fb5741461035b578063e0a313391461038b57610100565b806375b024051461025f5780637e9da7a21461028f578063809741ed146102bf5780638da5cb5b146102ef57610100565b8063334503bf116100d3578063334503bf1461019f57806347402bea146101cf5780635eb2088e146101ff5780636da42a151461022f57610100565b80630e0578f514610105578063127e11971461013557806318df238814610153578063299821f614610183575b600080fd5b61011f600480360381019061011a9190613ca8565b6103bb565b60405161012c9190613e37565b60405180910390f35b61013d61056b565b60405161014a9190613e62565b60405180910390f35b61016d60048036038101906101689190613ea9565b610583565b60405161017a9190613fbf565b60405180910390f35b61019d60048036038101906101989190614046565b61072e565b005b6101b960048036038101906101b49190614093565b610930565b6040516101c69190613fbf565b60405180910390f35b6101e960048036038101906101e4919061413a565b610c07565b6040516101f69190614228565b60405180910390f35b61021960048036038101906102149190614243565b6118f1565b6040516102269190613fbf565b60405180910390f35b61024960048036038101906102449190613ca8565b611d4f565b6040516102569190613fbf565b60405180910390f35b610279600480360381019061027491906143e5565b611f12565b6040516102869190613fbf565b60405180910390f35b6102a960048036038101906102a49190614093565b61211d565b6040516102b69190613fbf565b60405180910390f35b6102d960048036038101906102d4919061442e565b6123f4565b6040516102e69190613fbf565b60405180910390f35b6102f7612705565b6040516103049190613e62565b60405180910390f35b6103276004803603810190610322919061446e565b61272b565b6040516103349190613fbf565b60405180910390f35b6103456128e9565b6040516103529190614228565b60405180910390f35b610375600480360381019061037091906143e5565b6128ef565b6040516103829190613fbf565b60405180910390f35b6103a560048036038101906103a09190614093565b612c01565b6040516103b29190613fbf565b60405180910390f35b6103c3613b45565b6006600083815260200190815260200160002060405180610180016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016008820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160149054906101000a900460ff1660ff1660ff1681526020016009820160159054906101000a900460ff1660ff1660ff16815250509050919050565b73275069215717568faaa7ea54d0d5c03dbcfbd7d281565b6060600061059386866000612d72565b9050600060016000838152602001908152602001600020600086815260200190815260200160002060000154116105f157600160008281526020019081526020016000206000808152602001908152602001600020600201546105f3565b835b935060008060028561060591906144f0565b67ffffffffffffffff81111561061e5761061d6142a7565b5b60405190808252806020026020018201604052801561064c5781602001602082028036833780820191505090505b50905060005b8581101561071f57600087031561071f57868284806106709061454a565b95508151811061068357610682614592565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600001548284806106c39061454a565b9550815181106106d6576106d5614592565b5b60200260200101818152505060016000858152602001908152602001600020600088815260200190815260200160002060020154965080806107179061454a565b915050610652565b50809350505050949350505050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b59061461e565b60405180910390fd5b60005b8282905081101561092b576008600660008585858181106107e5576107e4614592565b5b90506020020135815260200190815260200160002060090160159054906101000a900460ff1660ff1603610918576006600084848481811061082a57610829614592565b5b9050602002013581526020019081526020016000206000808201600090556001820160009055600282016000905560038201600090556004820160009055600582016000905560068201600090556007820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160146101000a81549060ff02191690556009820160156101000a81549060ff021916905550505b80806109239061454a565b9150506107c1565b505050565b6060600061093f878787612df5565b9050600360008281526020019081526020016000206000858152602001908152602001600020600101549350600084036109c557600167ffffffffffffffff81111561098e5761098d6142a7565b5b6040519080825280602002602001820160405280156109bc5781602001602082028036833780820191505090505b50915050610bfe565b6000806006856109d591906144f0565b67ffffffffffffffff8111156109ee576109ed6142a7565b5b604051908082528060200260200182016040528015610a1c5781602001602082028036833780820191505090505b50905060005b85811015610bf6576000870315610bf65786828480610a409061454a565b955081518110610a5357610a52614592565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff16828480610a929061454a565b955081518110610aa557610aa4614592565b5b6020026020010181815250506006600088815260200190815260200160002060000154828480610ad49061454a565b955081518110610ae757610ae6614592565b5b6020026020010181815250506006600088815260200190815260200160002060030154828480610b169061454a565b955081518110610b2957610b28614592565b5b6020026020010181815250506006600088815260200190815260200160002060020154828480610b589061454a565b955081518110610b6b57610b6a614592565b5b6020026020010181815250506006600088815260200190815260200160002060040154828480610b9a9061454a565b955081518110610bad57610bac614592565b5b6020026020010181815250506003600085815260200190815260200160002060008881526020019081526020016000206001015496508080610bee9061454a565b915050610a22565b508093505050505b95945050505050565b600073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c5557600080fd5b610c5d613b45565b4281600001818152505089816040018181525050878160800181815250508681610140019060ff16908160ff1681525050858160600181815250508a8160e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508881610100019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508b81610120019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181610160019060ff16908160ff16815250506000808154610d649061454a565b919050819055506000805490506000610d8a610d828e8d6000612d72565b888a8c612e3c565b809250819850505080156116ca57610da0613bee565b610dac8c8f6000612d72565b81600001818152505060016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250505b6000816020015111156115045760016000826000015181526020019081526020016000206000826020015181526020019081526020016000206000015481604001818152505060018a60ff1603610e4c578060400151891161150457610e58565b80604001518910611504575b60008603610f0557600984610160019060ff16908160ff168152505073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128f86610120015187604001516040518463ffffffff1660e01b8152600401610ece9392919061463e565b600060405180830381600087803b158015610ee857600080fd5b505af1158015610efc573d6000803e3d6000fd5b50505050611504565b85610f0f90614675565b95506006600082602001518152602001908152602001600020600401548160600181815250508060600151846040015110610f4e578060600151610f54565b83604001515b8160800181815250508360400151846080015182608001518660400151610f7b919061469e565b610f8591906144f0565b610f8f9190614701565b8460800181815250506000846080015114610fae578060800151610fb4565b83604001515b8160a00181815250508060a0015184604001818151610fd3919061469e565b915081815250508060a001518460a001818151610ff09190614732565b9150818152505068056bc75e2d63100000878260a0015161101191906144f0565b61101b9190614701565b8160c00181815250508060c00151816101000181815161103b9190614732565b91508181525050600660008260200151815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681610140019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128f8361014001518460c001518560a00151611100919061469e565b6040518463ffffffff1660e01b815260040161111e9392919061463e565b600060405180830381600087803b15801561113857600080fd5b505af115801561114c573d6000803e3d6000fd5b505050508060c001518160a00151611164919061469e565b6006600083602001518152602001908152602001600020600601600082825461118d9190614732565b925050819055508060c00151600660008360200151815260200190815260200160002060010160008282546111c29190614732565b92505081905550806060015160066000836020015181526020019081526020016000206002015482608001516111f891906144f0565b6112029190614701565b8160a001818152505068056bc75e2d63100000878260a0015161122591906144f0565b61122f9190614701565b8160c00181815250508060a0015160066000836020015181526020019081526020016000206002016000828254611266919061469e565b9250508190555080608001518160600151611281919061469e565b6006600083602001518152602001908152602001600020600401819055508060a00151600660008360200151815260200190815260200160002060050160008282546112cd9190614732565b925050819055508060c0015181610120018181516112eb9190614732565b915081815250508060c001518160a00151611306919061469e565b8160e0018181516113179190614732565b915081815250508060c001518160a00151611332919061469e565b8460c0018181516113439190614732565b915081815250508060c00151846020018181516113609190614732565b915081815250504260066000836020015181526020019081526020016000206000018190555080602001517f271adf7ca5026da9466c7e2ee50294432b6518106821bb0baa27adfbe5203bad60405160405180910390a2600060066000836020015181526020019081526020016000206002015403611492576007600660008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061141f8160000151826020015161321b565b6114348c8f8361014001518460200151613310565b6114498c8f83610140015184602001516135ce565b6114588c8f8360200151613695565b60016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250506114c6565b60068060008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055505b60008460400151036114eb57600784610160019060ff16908160ff1681525050611504565b600684610160019060ff16908160ff1681525050610deb565b60008160e00151111561159e5773275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128d8661012001518460e001516040518463ffffffff1660e01b815260040161156b9392919061463e565b600060405180830381600087803b15801561158557600080fd5b505af1158015611599573d6000803e3d6000fd5b505050505b600081610100015111156116335773275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663fd9be5228f8361010001516040518363ffffffff1660e01b8152600401611600929190614766565b600060405180830381600087803b15801561161a57600080fd5b505af115801561162e573d6000803e3d6000fd5b505050505b600081610120015111156116c85773275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663fd9be5228d8361012001516040518363ffffffff1660e01b8152600401611695929190614766565b600060405180830381600087803b1580156116af57600080fd5b505af11580156116c3573d6000803e3d6000fd5b505050505b505b8260066000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101008201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160090160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101408201518160090160146101000a81548160ff021916908360ff1602179055506101608201518160090160156101000a81548160ff021916908360ff160217905550905050600183610160015160ff1614806118615750600683610160015160ff16145b156118935761187d6118758e8d6000612d72565b88848b613748565b61188e8d8c85610120015185613833565b6118b0565b6118a48d8c856101200151856135ce565b6118af8d8c84613695565b5b817f2f539bcf68b0eef24f9fef1ae5ad7dd5a37f80a2fab34f406ad2b92c779d606460405160405180910390a28193505050509a9950505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101549250600083036119a257600167ffffffffffffffff81111561196c5761196b6142a7565b5b60405190808252806020026020018201604052801561199a5781602001602082028036833780820191505090505b509050611d48565b6000806009846119b291906144f0565b67ffffffffffffffff8111156119cb576119ca6142a7565b5b6040519080825280602002602001820160405280156119f95781602001602082028036833780820191505090505b50905060005b84811015611d41576000860315611d415785828480611a1d9061454a565b955081518110611a3057611a2f614592565b5b6020026020010181815250506006600087815260200190815260200160002060000154828480611a5f9061454a565b955081518110611a7257611a71614592565b5b6020026020010181815250506006600087815260200190815260200160002060030154828480611aa19061454a565b955081518110611ab457611ab3614592565b5b6020026020010181815250506006600087815260200190815260200160002060020154828480611ae39061454a565b955081518110611af657611af5614592565b5b6020026020010181815250506006600087815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16828480611b5b9061454a565b955081518110611b6e57611b6d614592565b5b6020026020010181815250506006600087815260200190815260200160002060040154828480611b9d9061454a565b955081518110611bb057611baf614592565b5b6020026020010181815250506006600087815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16828480611c159061454a565b955081518110611c2857611c27614592565b5b6020026020010181815250506006600087815260200190815260200160002060090160149054906101000a900460ff1660ff16828480611c679061454a565b955081518110611c7a57611c79614592565b5b6020026020010181815250506006600087815260200190815260200160002060090160159054906101000a900460ff1660ff16828480611cb99061454a565b955081518110611ccc57611ccb614592565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206001015495508080611d399061454a565b9150506119ff565b5080925050505b9392505050565b60606000600667ffffffffffffffff811115611d6e57611d6d6142a7565b5b604051908082528060200260200182016040528015611d9c5781602001602082028036833780820191505090505b5090506006600084815260200190815260200160002060090160159054906101000a900460ff1660ff1681600081518110611dda57611dd9614592565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff1681600181518110611e2157611e20614592565b5b602002602001018181525050600660008481526020019081526020016000206002015481600281518110611e5857611e57614592565b5b602002602001018181525050600660008481526020019081526020016000206004015481600381518110611e8f57611e8e614592565b5b602002602001018181525050600660008481526020019081526020016000206005015481600481518110611ec657611ec5614592565b5b602002602001018181525050600660008481526020019081526020016000206006015481600581518110611efd57611efc614592565b5b60200260200101818152505080915050919050565b606060008060005b845181101561211257848181518110611f3657611f35614592565b5b602002602001015191506006600083815260200190815260200160002060090160159054906101000a900460ff1692503373ffffffffffffffffffffffffffffffffffffffff166006600084815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611ff6575060048360ff161480611fe7575060078360ff16145b80611ff5575060098360ff16145b5b156120dd5761207b6120756006600085815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633612df5565b83613a58565b60086006600084815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550817fbd000546857b596b03c884060c13e7d8c7a7ce52366d2f116f76688e6f000f6660405160405180910390a26120ff565b60008582815181106120f2576120f1614592565b5b6020026020010181815250505b808061210a9061454a565b915050611f1a565b508392505050919050565b6060600061212c878787612df5565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036121b257600167ffffffffffffffff81111561217b5761217a6142a7565b5b6040519080825280602002602001820160405280156121a95781602001602082028036833780820191505090505b509150506123eb565b6000806006856121c291906144f0565b67ffffffffffffffff8111156121db576121da6142a7565b5b6040519080825280602002602001820160405280156122095781602001602082028036833780820191505090505b50905060005b858110156123e35760008703156123e3578682848061222d9061454a565b9550815181106122405761223f614592565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061227f9061454a565b95508151811061229257612291614592565b5b60200260200101818152505060066000888152602001908152602001600020600001548284806122c19061454a565b9550815181106122d4576122d3614592565b5b60200260200101818152505060066000888152602001908152602001600020600301548284806123039061454a565b95508151811061231657612315614592565b5b60200260200101818152505060066000888152602001908152602001600020600501548284806123459061454a565b95508151811061235857612357614592565b5b60200260200101818152505060066000888152602001908152602001600020600601548284806123879061454a565b95508151811061239a57612399614592565b5b60200260200101818152505060046000858152602001908152602001600020600088815260200190815260200160002060010154965080806123db9061454a565b91505061220f565b508093505050505b95945050505050565b6060600061240484846001612d72565b905060006005600083815260200190815260200160002060006033811061242e5761242d614592565b5b015490506000810361248d57600167ffffffffffffffff811115612455576124546142a7565b5b6040519080825280602002602001820160405280156124835781602001602082028036833780820191505090505b50925050506126ff565b600080600061012c67ffffffffffffffff8111156124ae576124ad6142a7565b5b6040519080825280602002602001820160405280156124dc5781602001602082028036833780820191505090505b50905060005b60328110156126f5576005600087815260200190815260200160002085603381106125105761250f614592565b5b01549250828285806125219061454a565b96508151811061253457612533614592565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff168285806125739061454a565b96508151811061258657612585614592565b5b60200260200101818152505060066000848152602001908152602001600020600001548285806125b59061454a565b9650815181106125c8576125c7614592565b5b60200260200101818152505060066000848152602001908152602001600020600301548285806125f79061454a565b96508151811061260a57612609614592565b5b60200260200101818152505060066000848152602001908152602001600020600501548285806126399061454a565b96508151811061264c5761264b614592565b5b602002602001018181525050600660008481526020019081526020016000206006015482858061267b9061454a565b96508151811061268e5761268d614592565b5b6020026020010181815250506000856126a690614675565b955085036126e2576032945060006005600088815260200190815260200160002086603381106126d9576126d8614592565b5b015403156126f5575b80806126ed9061454a565b9150506124e2565b5080955050505050505b92915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600061273b85856000612d72565b9050600080600160008481526020019081526020016000206000808152602001908152602001600020600201549050600060038661277991906144f0565b67ffffffffffffffff811115612792576127916142a7565b5b6040519080825280602002602001820160405280156127c05781602001602082028036833780820191505090505b50905060005b868110156128da5760008303156128da5760066000848152602001908152602001600020600301548285806127fa9061454a565b96508151811061280d5761280c614592565b5b602002602001018181525050600660008481526020019081526020016000206002015482858061283c9061454a565b96508151811061284f5761284e614592565b5b602002602001018181525050600660008481526020019081526020016000206004015482858061287e9061454a565b96508151811061289157612890614592565b5b60200260200101818152505060016000868152602001908152602001600020600084815260200190815260200160002060020154925080806128d29061454a565b9150506127c6565b50809450505050509392505050565b60005481565b60606000806000806000805b8751811015612bf35787818151811061291757612916614592565b5b602002602001015194506006600086815260200190815260200160002060090160159054906101000a900460ff1695503373ffffffffffffffffffffffffffffffffffffffff166006600087815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480156129c9575060018660ff1614806129c8575060068660ff16145b5b15612bbe57600660008681526020019081526020016000206002015493506006600086815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692506006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915073275069215717568faaa7ea54d0d5c03dbcfbd7d273ffffffffffffffffffffffffffffffffffffffff1663d9caed128433876040518463ffffffff1660e01b8152600401612aaa9392919061463e565b600060405180830381600087803b158015612ac457600080fd5b505af1158015612ad8573d6000803e3d6000fd5b50505050426006600087815260200190815260200160002060000181905550600060066000878152602001908152602001600020600201819055506000600660008781526020019081526020016000206004018190555060046006600087815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550612b74612b6e84846000612d72565b8661321b565b612b8083833388613310565b612b8c838333886135ce565b847f935c9ad2f1fda9d7eae0d2a512f1521cb7190ee06165414e722366a65975fb6b60405160405180910390a2612be0565b6000888281518110612bd357612bd2614592565b5b6020026020010181815250505b8080612beb9061454a565b9150506128fb565b508695505050505050919050565b60606000612c10878787612df5565b905060046000828152602001908152602001600020600085815260200190815260200160002060010154935060008403612c9657600167ffffffffffffffff811115612c5f57612c5e6142a7565b5b604051908082528060200260200182016040528015612c8d5781602001602082028036833780820191505090505b50915050612d69565b6000808467ffffffffffffffff811115612cb357612cb26142a7565b5b604051908082528060200260200182016040528015612ce15781602001602082028036833780820191505090505b50905060005b85811015612d61576000870315612d615786828480612d059061454a565b955081518110612d1857612d17614592565b5b6020026020010181815250506004600085815260200190815260200160002060008881526020019081526020016000206001015496508080612d599061454a565b915050612ce7565b508093505050505b95945050505050565b60008115612dc0578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610612db4578284612db7565b83835b80945081955050505b8383604051602001612dd39291906147d7565b6040516020818303038152906040528051906020012060001c90509392505050565b600080612e0485856001612d72565b90508083604051602001612e19929190614824565b6040516020818303038152906040528051906020012060001c9150509392505050565b6000806000806000600160008a815260200190815260200160002060008981526020019081526020016000206000015411612e9e5760016000898152602001908152602001600020600080815260200190815260200160002060020154612ea0565b865b965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060008203612ee35760006001935093505050613212565b60018560ff16036130825781861015612fd0576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b81861015612f9b5760008103612f3f57866001935093505050613212565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600101549050612f21565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613212565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b818610613074576000810361301857600080935093505050613212565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600201549050612ffb565b866000935093505050613212565b81861115613164576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b8186111561312f57600081036130d357866001935093505050613212565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206001015490506130b5565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613212565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861161320857600081036131ac57600080935093505050613212565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060020154905061318f565b8660009350935050505b94509492505050565b600060016000848152602001908152602001600020600083815260200190815260200160002060010154905060006001600085815260200190815260200160002060008481526020019081526020016000206002015490508160016000868152602001908152602001600020600083815260200190815260200160002060010181905550806001600086815260200190815260200160002060008481526020019081526020016000206002018190555060016000858152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505060006134e0878787612df5565b9050600360008281526020019081526020016000206000858152602001908152602001600020600001549250600360008281526020019081526020016000206000858152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555081600360008381526020019081526020016000206000858152602001908152602001600020600101819055506003600082815260200190815260200160002060008581526020019081526020016000206000808201600090556001820160009055505050505050505050565b60006135db858585612df5565b90506000600460008381526020019081526020016000206000808152602001908152602001600020600101549050826004600084815260200190815260200160002060008381526020019081526020016000206000018190555082600460008481526020019081526020016000206000808152602001908152602001600020600101819055508060046000848152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006136a384846001612d72565b90506000600560008381526020019081526020016000206000603381106136cd576136cc614592565b5b01549050603281036136de57600090505b806136e89061454a565b9050826005600084815260200190815260200160002082603381106137105761370f614592565b5b0181905550806005600084815260200190815260200160002060006033811061373c5761373b614592565b5b01819055505050505050565b6000600160008681526020019081526020016000206000858152602001908152602001600020600101549050826001600087815260200190815260200160002060008681526020019081526020016000206001018190555082600160008781526020019081526020016000206000838152602001908152602001600020600201819055506040518060600160405280838152602001828152602001858152506001600087815260200190815260200160002060008581526020019081526020016000206000820151816000015560208201518160010155604082015181600201559050505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060010154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206001018190555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001018190555060006139a0868686612df5565b9050600360008281526020019081526020016000206000808152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555082600360008381526020019081526020016000206000808152602001908152602001600020600101819055508160036000838152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006004600084815260200190815260200160002060008381526020019081526020016000206000015490506000600460008581526020019081526020016000206000848152602001908152602001600020600101549050816004600086815260200190815260200160002060008381526020019081526020016000206000018190555080600460008681526020019081526020016000206000848152602001908152602001600020600101819055506004600085815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505050505050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b613c8581613c72565b8114613c9057600080fd5b50565b600081359050613ca281613c7c565b92915050565b600060208284031215613cbe57613cbd613c68565b5b6000613ccc84828501613c93565b91505092915050565b613cde81613c72565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613d0f82613ce4565b9050919050565b613d1f81613d04565b82525050565b600060ff82169050919050565b613d3b81613d25565b82525050565b61018082016000820151613d586000850182613cd5565b506020820151613d6b6020850182613cd5565b506040820151613d7e6040850182613cd5565b506060820151613d916060850182613cd5565b506080820151613da46080850182613cd5565b5060a0820151613db760a0850182613cd5565b5060c0820151613dca60c0850182613cd5565b5060e0820151613ddd60e0850182613d16565b50610100820151613df2610100850182613d16565b50610120820151613e07610120850182613d16565b50610140820151613e1c610140850182613d32565b50610160820151613e31610160850182613d32565b50505050565b600061018082019050613e4d6000830184613d41565b92915050565b613e5c81613d04565b82525050565b6000602082019050613e776000830184613e53565b92915050565b613e8681613d04565b8114613e9157600080fd5b50565b600081359050613ea381613e7d565b92915050565b60008060008060808587031215613ec357613ec2613c68565b5b6000613ed187828801613e94565b9450506020613ee287828801613e94565b9350506040613ef387828801613c93565b9250506060613f0487828801613c93565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000613f488383613cd5565b60208301905092915050565b6000602082019050919050565b6000613f6c82613f10565b613f768185613f1b565b9350613f8183613f2c565b8060005b83811015613fb2578151613f998882613f3c565b9750613fa483613f54565b925050600181019050613f85565b5085935050505092915050565b60006020820190508181036000830152613fd98184613f61565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261400657614005613fe1565b5b8235905067ffffffffffffffff81111561402357614022613fe6565b5b60208301915083602082028301111561403f5761403e613feb565b5b9250929050565b6000806020838503121561405d5761405c613c68565b5b600083013567ffffffffffffffff81111561407b5761407a613c6d565b5b61408785828601613ff0565b92509250509250929050565b600080600080600060a086880312156140af576140ae613c68565b5b60006140bd88828901613e94565b95505060206140ce88828901613e94565b94505060406140df88828901613e94565b93505060606140f088828901613c93565b925050608061410188828901613c93565b9150509295509295909350565b61411781613d25565b811461412257600080fd5b50565b6000813590506141348161410e565b92915050565b6000806000806000806000806000806101408b8d03121561415e5761415d613c68565b5b600061416c8d828e01613e94565b9a5050602061417d8d828e01613e94565b995050604061418e8d828e01613c93565b985050606061419f8d828e01613e94565b97505060806141b08d828e01613c93565b96505060a06141c18d828e01614125565b95505060c06141d28d828e01613c93565b94505060e06141e38d828e01613c93565b9350506101006141f58d828e01613c93565b9250506101206142078d828e01613c93565b9150509295989b9194979a5092959850565b61422281613c72565b82525050565b600060208201905061423d6000830184614219565b92915050565b60008060006060848603121561425c5761425b613c68565b5b600061426a86828701613e94565b935050602061427b86828701613c93565b925050604061428c86828701613c93565b9150509250925092565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6142df82614296565b810181811067ffffffffffffffff821117156142fe576142fd6142a7565b5b80604052505050565b6000614311613c5e565b905061431d82826142d6565b919050565b600067ffffffffffffffff82111561433d5761433c6142a7565b5b602082029050602081019050919050565b600061436161435c84614322565b614307565b9050808382526020820190506020840283018581111561438457614383613feb565b5b835b818110156143ad57806143998882613c93565b845260208401935050602081019050614386565b5050509392505050565b600082601f8301126143cc576143cb613fe1565b5b81356143dc84826020860161434e565b91505092915050565b6000602082840312156143fb576143fa613c68565b5b600082013567ffffffffffffffff81111561441957614418613c6d565b5b614425848285016143b7565b91505092915050565b6000806040838503121561444557614444613c68565b5b600061445385828601613e94565b925050602061446485828601613e94565b9150509250929050565b60008060006060848603121561448757614486613c68565b5b600061449586828701613e94565b93505060206144a686828701613e94565b92505060406144b786828701613c93565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006144fb82613c72565b915061450683613c72565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561453f5761453e6144c1565b5b828202905092915050565b600061455582613c72565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614587576145866144c1565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732e00000000000000600082015250565b60006146086019836145c1565b9150614613826145d2565b602082019050919050565b60006020820190508181036000830152614637816145fb565b9050919050565b60006060820190506146536000830186613e53565b6146606020830185613e53565b61466d6040830184614219565b949350505050565b600061468082613c72565b915060008203614693576146926144c1565b5b600182039050919050565b60006146a982613c72565b91506146b483613c72565b92508282039050818111156146cc576146cb6144c1565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061470c82613c72565b915061471783613c72565b925082614727576147266146d2565b5b828204905092915050565b600061473d82613c72565b915061474883613c72565b92508282019050808211156147605761475f6144c1565b5b92915050565b600060408201905061477b6000830185613e53565b6147886020830184614219565b9392505050565b60008160601b9050919050565b60006147a78261478f565b9050919050565b60006147b98261479c565b9050919050565b6147d16147cc82613d04565b6147ae565b82525050565b60006147e382856147c0565b6014820191506147f382846147c0565b6014820191508190509392505050565b6000819050919050565b61481e61481982613c72565b614803565b82525050565b6000614830828561480d565b60208201915061484082846147c0565b601482019150819050939250505056fea26469706673582212205148ac67da01a6975108de201292291b3ca6d7b06ba3a7e54c5e334bf685ce0964736f6c63430008100033