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:22.515028Z
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 = 0x5cec09F125f4839656164A5109BC076DAAbD6Ed6; // Контракт с депозитами 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 getLockedTokensForOracle(uint _id1, uint _id2) public view returns (uint [] memory) // функция возвращает заблокированные в контракте токены у 2-х запрашиваемых ордеров в одной торговой паре { // возвращает массив [токен1, количество1, токен2, количество2] uint[] memory result = new uint[](4); address _token1; uint _value1; address _token2; uint _value2; uint8 _status1 = orders[_id1].order_status; // статус первого ордера uint8 _status2 = orders[_id2].order_status; // статус второго ордера if(_status1 > 0){ // если ордер существует или существовал ранее. Тогда возьмем адреса токенов из него (_token1, _token2) = (orders[_id1].token_in, orders[_id1].token_out); } else{ // Адреса токенов берем из второго ордера (_token1, _token2) = (orders[_id2].token_in, orders[_id2].token_out); } if((_status1 == 1) || (_status1 == 6) || (_status1 == 7) || (_status1 == 9)){ // считаем количество токенов которое удерживает контракт if(_token1 == orders[_id1].token_in){ _value1 += orders[_id1].value_in; _value2 += orders[_id1].exec_out; } else{ _value2 += orders[_id1].value_in; _value1 += orders[_id1].exec_out; } } if((_status2 == 1) || (_status2 == 6) || (_status2 == 7) || (_status2 == 9)){ // считаем количество токенов которое удерживает контракт if(_token1 == orders[_id2].token_in){ _value1 += orders[_id2].value_in; _value2 += orders[_id2].exec_out; } else{ _value2 += orders[_id2].value_in; _value1 += orders[_id2].exec_out; } } result[0] = uint256(uint160(_token1)); result[1] = _value1; result[2] = uint256(uint160(_token2)); result[3] = _value2; 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":"getLockedTokensForOracle","inputs":[{"type":"uint256","name":"_id1","internalType":"uint256"},{"type":"uint256","name":"_id2","internalType":"uint256"}]},{"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
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50614dd1806100756000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80636da42a15116100a25780638da5cb5b116100715780638da5cb5b1461032a5780639435298b14610348578063af640d0f14610378578063b55fb57414610396578063e0a31339146103c65761010b565b80636da42a151461026a57806375b024051461029a5780637e9da7a2146102ca578063809741ed146102fa5761010b565b8063334503bf116100de578063334503bf146101aa57806336511013146101da57806347402bea1461020a5780635eb2088e1461023a5761010b565b80630e0578f514610110578063127e11971461014057806318df23881461015e578063299821f61461018e575b600080fd5b61012a600480360381019061012591906141b3565b6103f6565b6040516101379190614342565b60405180910390f35b6101486105a6565b604051610155919061436d565b60405180910390f35b610178600480360381019061017391906143b4565b6105be565b60405161018591906144ca565b60405180910390f35b6101a860048036038101906101a39190614551565b610769565b005b6101c460048036038101906101bf919061459e565b61096b565b6040516101d191906144ca565b60405180910390f35b6101f460048036038101906101ef9190614619565b610c42565b60405161020191906144ca565b60405180910390f35b610224600480360381019061021f9190614685565b611112565b6040516102319190614773565b60405180910390f35b610254600480360381019061024f919061478e565b611dfc565b60405161026191906144ca565b60405180910390f35b610284600480360381019061027f91906141b3565b61225a565b60405161029191906144ca565b60405180910390f35b6102b460048036038101906102af9190614930565b61241d565b6040516102c191906144ca565b60405180910390f35b6102e460048036038101906102df919061459e565b612628565b6040516102f191906144ca565b60405180910390f35b610314600480360381019061030f9190614979565b6128ff565b60405161032191906144ca565b60405180910390f35b610332612c10565b60405161033f919061436d565b60405180910390f35b610362600480360381019061035d91906149b9565b612c36565b60405161036f91906144ca565b60405180910390f35b610380612df4565b60405161038d9190614773565b60405180910390f35b6103b060048036038101906103ab9190614930565b612dfa565b6040516103bd91906144ca565b60405180910390f35b6103e060048036038101906103db919061459e565b61310c565b6040516103ed91906144ca565b60405180910390f35b6103fe614050565b6006600083815260200190815260200160002060405180610180016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016008820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160149054906101000a900460ff1660ff1660ff1681526020016009820160159054906101000a900460ff1660ff1660ff16815250509050919050565b735cec09f125f4839656164a5109bc076daabd6ed681565b606060006105ce8686600061327d565b90506000600160008381526020019081526020016000206000868152602001908152602001600020600001541161062c576001600082815260200190815260200160002060008081526020019081526020016000206002015461062e565b835b93506000806002856106409190614a3b565b67ffffffffffffffff811115610659576106586147f2565b5b6040519080825280602002602001820160405280156106875781602001602082028036833780820191505090505b50905060005b8581101561075a57600087031561075a57868284806106ab90614a95565b9550815181106106be576106bd614add565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600001548284806106fe90614a95565b95508151811061071157610710614add565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600201549650808061075290614a95565b91505061068d565b50809350505050949350505050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f090614b69565b60405180910390fd5b60005b82829050811015610966576008600660008585858181106108205761081f614add565b5b90506020020135815260200190815260200160002060090160159054906101000a900460ff1660ff1603610953576006600084848481811061086557610864614add565b5b9050602002013581526020019081526020016000206000808201600090556001820160009055600282016000905560038201600090556004820160009055600582016000905560068201600090556007820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160146101000a81549060ff02191690556009820160156101000a81549060ff021916905550505b808061095e90614a95565b9150506107fc565b505050565b6060600061097a878787613300565b905060036000828152602001908152602001600020600085815260200190815260200160002060010154935060008403610a0057600167ffffffffffffffff8111156109c9576109c86147f2565b5b6040519080825280602002602001820160405280156109f75781602001602082028036833780820191505090505b50915050610c39565b600080600685610a109190614a3b565b67ffffffffffffffff811115610a2957610a286147f2565b5b604051908082528060200260200182016040528015610a575781602001602082028036833780820191505090505b50905060005b85811015610c31576000870315610c315786828480610a7b90614a95565b955081518110610a8e57610a8d614add565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff16828480610acd90614a95565b955081518110610ae057610adf614add565b5b6020026020010181815250506006600088815260200190815260200160002060000154828480610b0f90614a95565b955081518110610b2257610b21614add565b5b6020026020010181815250506006600088815260200190815260200160002060030154828480610b5190614a95565b955081518110610b6457610b63614add565b5b6020026020010181815250506006600088815260200190815260200160002060020154828480610b9390614a95565b955081518110610ba657610ba5614add565b5b6020026020010181815250506006600088815260200190815260200160002060040154828480610bd590614a95565b955081518110610be857610be7614add565b5b6020026020010181815250506003600085815260200190815260200160002060008881526020019081526020016000206001015496508080610c2990614a95565b915050610a5d565b508093505050505b95945050505050565b60606000600467ffffffffffffffff811115610c6157610c606147f2565b5b604051908082528060200260200182016040528015610c8f5781602001602082028036833780820191505090505b5090506000806000806000600660008a815260200190815260200160002060090160159054906101000a900460ff1690506000600660008a815260200190815260200160002060090160159054906101000a900460ff16905060008260ff161115610d6f57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008c815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168095508197505050610de6565b600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1680955081975050505b60018260ff161480610dfb575060068260ff16145b80610e09575060078260ff16145b80610e17575060098260ff16145b15610f1c57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610ed257600660008b81526020019081526020016000206002015485610ea79190614b89565b9450600660008b81526020019081526020016000206006015483610ecb9190614b89565b9250610f1b565b600660008b81526020019081526020016000206002015483610ef49190614b89565b9250600660008b81526020019081526020016000206006015485610f189190614b89565b94505b5b60018160ff161480610f31575060068160ff16145b80610f3f575060078160ff16145b80610f4d575060098160ff16145b1561105257600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff160361100857600660008a81526020019081526020016000206002015485610fdd9190614b89565b9450600660008a815260200190815260200160002060060154836110019190614b89565b9250611051565b600660008a8152602001908152602001600020600201548361102a9190614b89565b9250600660008a8152602001908152602001600020600601548561104e9190614b89565b94505b5b8573ffffffffffffffffffffffffffffffffffffffff168760008151811061107d5761107c614add565b5b602002602001018181525050848760018151811061109e5761109d614add565b5b6020026020010181815250508373ffffffffffffffffffffffffffffffffffffffff16876002815181106110d5576110d4614add565b5b60200260200101818152505082876003815181106110f6576110f5614add565b5b6020026020010181815250508697505050505050505092915050565b6000735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461116057600080fd5b611168614050565b4281600001818152505089816040018181525050878160800181815250508681610140019060ff16908160ff1681525050858160600181815250508a8160e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508881610100019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508b81610120019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181610160019060ff16908160ff1681525050600080815461126f90614a95565b91905081905550600080549050600061129561128d8e8d600061327d565b888a8c613347565b80925081985050508015611bd5576112ab6140f9565b6112b78c8f600061327d565b81600001818152505060016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250505b600081602001511115611a0f5760016000826000015181526020019081526020016000206000826020015181526020019081526020016000206000015481604001818152505060018a60ff16036113575780604001518911611a0f57611363565b80604001518910611a0f575b6000860361141057600984610160019060ff16908160ff1681525050735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128f86610120015187604001516040518463ffffffff1660e01b81526004016113d993929190614bbd565b600060405180830381600087803b1580156113f357600080fd5b505af1158015611407573d6000803e3d6000fd5b50505050611a0f565b8561141a90614bf4565b9550600660008260200151815260200190815260200160002060040154816060018181525050806060015184604001511061145957806060015161145f565b83604001515b81608001818152505083604001518460800151826080015186604001516114869190614c1d565b6114909190614a3b565b61149a9190614c80565b84608001818152505060008460800151146114b95780608001516114bf565b83604001515b8160a00181815250508060a00151846040018181516114de9190614c1d565b915081815250508060a001518460a0018181516114fb9190614b89565b9150818152505068056bc75e2d63100000878260a0015161151c9190614a3b565b6115269190614c80565b8160c00181815250508060c0015181610100018181516115469190614b89565b91508181525050600660008260200151815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681610140019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128f8361014001518460c001518560a0015161160b9190614c1d565b6040518463ffffffff1660e01b815260040161162993929190614bbd565b600060405180830381600087803b15801561164357600080fd5b505af1158015611657573d6000803e3d6000fd5b505050508060c001518160a0015161166f9190614c1d565b600660008360200151815260200190815260200160002060060160008282546116989190614b89565b925050819055508060c00151600660008360200151815260200190815260200160002060010160008282546116cd9190614b89565b92505081905550806060015160066000836020015181526020019081526020016000206002015482608001516117039190614a3b565b61170d9190614c80565b8160a001818152505068056bc75e2d63100000878260a001516117309190614a3b565b61173a9190614c80565b8160c00181815250508060a00151600660008360200151815260200190815260200160002060020160008282546117719190614c1d565b925050819055508060800151816060015161178c9190614c1d565b6006600083602001518152602001908152602001600020600401819055508060a00151600660008360200151815260200190815260200160002060050160008282546117d89190614b89565b925050819055508060c0015181610120018181516117f69190614b89565b915081815250508060c001518160a001516118119190614c1d565b8160e0018181516118229190614b89565b915081815250508060c001518160a0015161183d9190614c1d565b8460c00181815161184e9190614b89565b915081815250508060c001518460200181815161186b9190614b89565b915081815250504260066000836020015181526020019081526020016000206000018190555080602001517f271adf7ca5026da9466c7e2ee50294432b6518106821bb0baa27adfbe5203bad60405160405180910390a260006006600083602001518152602001908152602001600020600201540361199d576007600660008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061192a81600001518260200151613726565b61193f8c8f836101400151846020015161381b565b6119548c8f8361014001518460200151613ad9565b6119638c8f8360200151613ba0565b60016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250506119d1565b60068060008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055505b60008460400151036119f657600784610160019060ff16908160ff1681525050611a0f565b600684610160019060ff16908160ff16815250506112f6565b60008160e001511115611aa957735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128d8661012001518460e001516040518463ffffffff1660e01b8152600401611a7693929190614bbd565b600060405180830381600087803b158015611a9057600080fd5b505af1158015611aa4573d6000803e3d6000fd5b505050505b60008161010001511115611b3e57735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663fd9be5228f8361010001516040518363ffffffff1660e01b8152600401611b0b929190614cb1565b600060405180830381600087803b158015611b2557600080fd5b505af1158015611b39573d6000803e3d6000fd5b505050505b60008161012001511115611bd357735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663fd9be5228d8361012001516040518363ffffffff1660e01b8152600401611ba0929190614cb1565b600060405180830381600087803b158015611bba57600080fd5b505af1158015611bce573d6000803e3d6000fd5b505050505b505b8260066000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101008201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160090160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101408201518160090160146101000a81548160ff021916908360ff1602179055506101608201518160090160156101000a81548160ff021916908360ff160217905550905050600183610160015160ff161480611d6c5750600683610160015160ff16145b15611d9e57611d88611d808e8d600061327d565b88848b613c53565b611d998d8c85610120015185613d3e565b611dbb565b611daf8d8c85610120015185613ad9565b611dba8d8c84613ba0565b5b817f2f539bcf68b0eef24f9fef1ae5ad7dd5a37f80a2fab34f406ad2b92c779d606460405160405180910390a28193505050509a9950505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154925060008303611ead57600167ffffffffffffffff811115611e7757611e766147f2565b5b604051908082528060200260200182016040528015611ea55781602001602082028036833780820191505090505b509050612253565b600080600984611ebd9190614a3b565b67ffffffffffffffff811115611ed657611ed56147f2565b5b604051908082528060200260200182016040528015611f045781602001602082028036833780820191505090505b50905060005b8481101561224c57600086031561224c5785828480611f2890614a95565b955081518110611f3b57611f3a614add565b5b6020026020010181815250506006600087815260200190815260200160002060000154828480611f6a90614a95565b955081518110611f7d57611f7c614add565b5b6020026020010181815250506006600087815260200190815260200160002060030154828480611fac90614a95565b955081518110611fbf57611fbe614add565b5b6020026020010181815250506006600087815260200190815260200160002060020154828480611fee90614a95565b95508151811061200157612000614add565b5b6020026020010181815250506006600087815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061206690614a95565b95508151811061207957612078614add565b5b60200260200101818152505060066000878152602001908152602001600020600401548284806120a890614a95565b9550815181106120bb576120ba614add565b5b6020026020010181815250506006600087815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061212090614a95565b95508151811061213357612132614add565b5b6020026020010181815250506006600087815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061217290614a95565b95508151811061218557612184614add565b5b6020026020010181815250506006600087815260200190815260200160002060090160159054906101000a900460ff1660ff168284806121c490614a95565b9550815181106121d7576121d6614add565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600101549550808061224490614a95565b915050611f0a565b5080925050505b9392505050565b60606000600667ffffffffffffffff811115612279576122786147f2565b5b6040519080825280602002602001820160405280156122a75781602001602082028036833780820191505090505b5090506006600084815260200190815260200160002060090160159054906101000a900460ff1660ff16816000815181106122e5576122e4614add565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff168160018151811061232c5761232b614add565b5b60200260200101818152505060066000848152602001908152602001600020600201548160028151811061236357612362614add565b5b60200260200101818152505060066000848152602001908152602001600020600401548160038151811061239a57612399614add565b5b6020026020010181815250506006600084815260200190815260200160002060050154816004815181106123d1576123d0614add565b5b60200260200101818152505060066000848152602001908152602001600020600601548160058151811061240857612407614add565b5b60200260200101818152505080915050919050565b606060008060005b845181101561261d5784818151811061244157612440614add565b5b602002602001015191506006600083815260200190815260200160002060090160159054906101000a900460ff1692503373ffffffffffffffffffffffffffffffffffffffff166006600084815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612501575060048360ff1614806124f2575060078360ff16145b80612500575060098360ff16145b5b156125e8576125866125806006600085815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633613300565b83613f63565b60086006600084815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550817fbd000546857b596b03c884060c13e7d8c7a7ce52366d2f116f76688e6f000f6660405160405180910390a261260a565b60008582815181106125fd576125fc614add565b5b6020026020010181815250505b808061261590614a95565b915050612425565b508392505050919050565b60606000612637878787613300565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036126bd57600167ffffffffffffffff811115612686576126856147f2565b5b6040519080825280602002602001820160405280156126b45781602001602082028036833780820191505090505b509150506128f6565b6000806006856126cd9190614a3b565b67ffffffffffffffff8111156126e6576126e56147f2565b5b6040519080825280602002602001820160405280156127145781602001602082028036833780820191505090505b50905060005b858110156128ee5760008703156128ee578682848061273890614a95565b95508151811061274b5761274a614add565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061278a90614a95565b95508151811061279d5761279c614add565b5b60200260200101818152505060066000888152602001908152602001600020600001548284806127cc90614a95565b9550815181106127df576127de614add565b5b602002602001018181525050600660008881526020019081526020016000206003015482848061280e90614a95565b95508151811061282157612820614add565b5b602002602001018181525050600660008881526020019081526020016000206005015482848061285090614a95565b95508151811061286357612862614add565b5b602002602001018181525050600660008881526020019081526020016000206006015482848061289290614a95565b9550815181106128a5576128a4614add565b5b60200260200101818152505060046000858152602001908152602001600020600088815260200190815260200160002060010154965080806128e690614a95565b91505061271a565b508093505050505b95945050505050565b6060600061290f8484600161327d565b905060006005600083815260200190815260200160002060006033811061293957612938614add565b5b015490506000810361299857600167ffffffffffffffff8111156129605761295f6147f2565b5b60405190808252806020026020018201604052801561298e5781602001602082028036833780820191505090505b5092505050612c0a565b600080600061012c67ffffffffffffffff8111156129b9576129b86147f2565b5b6040519080825280602002602001820160405280156129e75781602001602082028036833780820191505090505b50905060005b6032811015612c0057600560008781526020019081526020016000208560338110612a1b57612a1a614add565b5b0154925082828580612a2c90614a95565b965081518110612a3f57612a3e614add565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff16828580612a7e90614a95565b965081518110612a9157612a90614add565b5b6020026020010181815250506006600084815260200190815260200160002060000154828580612ac090614a95565b965081518110612ad357612ad2614add565b5b6020026020010181815250506006600084815260200190815260200160002060030154828580612b0290614a95565b965081518110612b1557612b14614add565b5b6020026020010181815250506006600084815260200190815260200160002060050154828580612b4490614a95565b965081518110612b5757612b56614add565b5b6020026020010181815250506006600084815260200190815260200160002060060154828580612b8690614a95565b965081518110612b9957612b98614add565b5b602002602001018181525050600085612bb190614bf4565b95508503612bed57603294506000600560008881526020019081526020016000208660338110612be457612be3614add565b5b01540315612c00575b8080612bf890614a95565b9150506129ed565b5080955050505050505b92915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606000612c468585600061327d565b90506000806001600084815260200190815260200160002060008081526020019081526020016000206002015490506000600386612c849190614a3b565b67ffffffffffffffff811115612c9d57612c9c6147f2565b5b604051908082528060200260200182016040528015612ccb5781602001602082028036833780820191505090505b50905060005b86811015612de5576000830315612de5576006600084815260200190815260200160002060030154828580612d0590614a95565b965081518110612d1857612d17614add565b5b6020026020010181815250506006600084815260200190815260200160002060020154828580612d4790614a95565b965081518110612d5a57612d59614add565b5b6020026020010181815250506006600084815260200190815260200160002060040154828580612d8990614a95565b965081518110612d9c57612d9b614add565b5b6020026020010181815250506001600086815260200190815260200160002060008481526020019081526020016000206002015492508080612ddd90614a95565b915050612cd1565b50809450505050509392505050565b60005481565b60606000806000806000805b87518110156130fe57878181518110612e2257612e21614add565b5b602002602001015194506006600086815260200190815260200160002060090160159054906101000a900460ff1695503373ffffffffffffffffffffffffffffffffffffffff166006600087815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612ed4575060018660ff161480612ed3575060068660ff16145b5b156130c957600660008681526020019081526020016000206002015493506006600086815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692506006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128433876040518463ffffffff1660e01b8152600401612fb593929190614bbd565b600060405180830381600087803b158015612fcf57600080fd5b505af1158015612fe3573d6000803e3d6000fd5b50505050426006600087815260200190815260200160002060000181905550600060066000878152602001908152602001600020600201819055506000600660008781526020019081526020016000206004018190555060046006600087815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061307f6130798484600061327d565b86613726565b61308b8383338861381b565b61309783833388613ad9565b847f935c9ad2f1fda9d7eae0d2a512f1521cb7190ee06165414e722366a65975fb6b60405160405180910390a26130eb565b60008882815181106130de576130dd614add565b5b6020026020010181815250505b80806130f690614a95565b915050612e06565b508695505050505050919050565b6060600061311b878787613300565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036131a157600167ffffffffffffffff81111561316a576131696147f2565b5b6040519080825280602002602001820160405280156131985781602001602082028036833780820191505090505b50915050613274565b6000808467ffffffffffffffff8111156131be576131bd6147f2565b5b6040519080825280602002602001820160405280156131ec5781602001602082028036833780820191505090505b50905060005b8581101561326c57600087031561326c578682848061321090614a95565b95508151811061322357613222614add565b5b602002602001018181525050600460008581526020019081526020016000206000888152602001908152602001600020600101549650808061326490614a95565b9150506131f2565b508093505050505b95945050505050565b600081156132cb578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16106132bf5782846132c2565b83835b80945081955050505b83836040516020016132de929190614d22565b6040516020818303038152906040528051906020012060001c90509392505050565b60008061330f8585600161327d565b90508083604051602001613324929190614d6f565b6040516020818303038152906040528051906020012060001c9150509392505050565b6000806000806000600160008a8152602001908152602001600020600089815260200190815260200160002060000154116133a957600160008981526020019081526020016000206000808152602001908152602001600020600201546133ab565b865b9650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600082036133ee576000600193509350505061371d565b60018560ff160361358d57818610156134db576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b818610156134a6576000810361344a5786600193509350505061371d565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060010154905061342c565b60016000898152602001908152602001600020600088815260200190815260200160002060020154600093509350505061371d565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861061357f57600081036135235760008093509350505061371d565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600201549050613506565b86600093509350505061371d565b8186111561366f576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b8186111561363a57600081036135de5786600193509350505061371d565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206001015490506135c0565b60016000898152602001908152602001600020600088815260200190815260200160002060020154600093509350505061371d565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861161371357600081036136b75760008093509350505061371d565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060020154905061369a565b8660009350935050505b94509492505050565b600060016000848152602001908152602001600020600083815260200190815260200160002060010154905060006001600085815260200190815260200160002060008481526020019081526020016000206002015490508160016000868152602001908152602001600020600083815260200190815260200160002060010181905550806001600086815260200190815260200160002060008481526020019081526020016000206002018190555060016000858152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505060006139eb878787613300565b9050600360008281526020019081526020016000206000858152602001908152602001600020600001549250600360008281526020019081526020016000206000858152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555081600360008381526020019081526020016000206000858152602001908152602001600020600101819055506003600082815260200190815260200160002060008581526020019081526020016000206000808201600090556001820160009055505050505050505050565b6000613ae6858585613300565b90506000600460008381526020019081526020016000206000808152602001908152602001600020600101549050826004600084815260200190815260200160002060008381526020019081526020016000206000018190555082600460008481526020019081526020016000206000808152602001908152602001600020600101819055508060046000848152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b6000613bae8484600161327d565b9050600060056000838152602001908152602001600020600060338110613bd857613bd7614add565b5b0154905060328103613be957600090505b80613bf390614a95565b905082600560008481526020019081526020016000208260338110613c1b57613c1a614add565b5b01819055508060056000848152602001908152602001600020600060338110613c4757613c46614add565b5b01819055505050505050565b6000600160008681526020019081526020016000206000858152602001908152602001600020600101549050826001600087815260200190815260200160002060008681526020019081526020016000206001018190555082600160008781526020019081526020016000206000838152602001908152602001600020600201819055506040518060600160405280838152602001828152602001858152506001600087815260200190815260200160002060008581526020019081526020016000206000820151816000015560208201518160010155604082015181600201559050505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060010154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206001018190555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101819055506000613eab868686613300565b9050600360008281526020019081526020016000206000808152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555082600360008381526020019081526020016000206000808152602001908152602001600020600101819055508160036000838152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006004600084815260200190815260200160002060008381526020019081526020016000206000015490506000600460008581526020019081526020016000206000848152602001908152602001600020600101549050816004600086815260200190815260200160002060008381526020019081526020016000206000018190555080600460008681526020019081526020016000206000848152602001908152602001600020600101819055506004600085815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505050505050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6141908161417d565b811461419b57600080fd5b50565b6000813590506141ad81614187565b92915050565b6000602082840312156141c9576141c8614173565b5b60006141d78482850161419e565b91505092915050565b6141e98161417d565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061421a826141ef565b9050919050565b61422a8161420f565b82525050565b600060ff82169050919050565b61424681614230565b82525050565b6101808201600082015161426360008501826141e0565b50602082015161427660208501826141e0565b50604082015161428960408501826141e0565b50606082015161429c60608501826141e0565b5060808201516142af60808501826141e0565b5060a08201516142c260a08501826141e0565b5060c08201516142d560c08501826141e0565b5060e08201516142e860e0850182614221565b506101008201516142fd610100850182614221565b50610120820151614312610120850182614221565b5061014082015161432761014085018261423d565b5061016082015161433c61016085018261423d565b50505050565b600061018082019050614358600083018461424c565b92915050565b6143678161420f565b82525050565b6000602082019050614382600083018461435e565b92915050565b6143918161420f565b811461439c57600080fd5b50565b6000813590506143ae81614388565b92915050565b600080600080608085870312156143ce576143cd614173565b5b60006143dc8782880161439f565b94505060206143ed8782880161439f565b93505060406143fe8782880161419e565b925050606061440f8782880161419e565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061445383836141e0565b60208301905092915050565b6000602082019050919050565b60006144778261441b565b6144818185614426565b935061448c83614437565b8060005b838110156144bd5781516144a48882614447565b97506144af8361445f565b925050600181019050614490565b5085935050505092915050565b600060208201905081810360008301526144e4818461446c565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112614511576145106144ec565b5b8235905067ffffffffffffffff81111561452e5761452d6144f1565b5b60208301915083602082028301111561454a576145496144f6565b5b9250929050565b6000806020838503121561456857614567614173565b5b600083013567ffffffffffffffff81111561458657614585614178565b5b614592858286016144fb565b92509250509250929050565b600080600080600060a086880312156145ba576145b9614173565b5b60006145c88882890161439f565b95505060206145d98882890161439f565b94505060406145ea8882890161439f565b93505060606145fb8882890161419e565b925050608061460c8882890161419e565b9150509295509295909350565b600080604083850312156146305761462f614173565b5b600061463e8582860161419e565b925050602061464f8582860161419e565b9150509250929050565b61466281614230565b811461466d57600080fd5b50565b60008135905061467f81614659565b92915050565b6000806000806000806000806000806101408b8d0312156146a9576146a8614173565b5b60006146b78d828e0161439f565b9a505060206146c88d828e0161439f565b99505060406146d98d828e0161419e565b98505060606146ea8d828e0161439f565b97505060806146fb8d828e0161419e565b96505060a061470c8d828e01614670565b95505060c061471d8d828e0161419e565b94505060e061472e8d828e0161419e565b9350506101006147408d828e0161419e565b9250506101206147528d828e0161419e565b9150509295989b9194979a5092959850565b61476d8161417d565b82525050565b60006020820190506147886000830184614764565b92915050565b6000806000606084860312156147a7576147a6614173565b5b60006147b58682870161439f565b93505060206147c68682870161419e565b92505060406147d78682870161419e565b9150509250925092565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61482a826147e1565b810181811067ffffffffffffffff82111715614849576148486147f2565b5b80604052505050565b600061485c614169565b90506148688282614821565b919050565b600067ffffffffffffffff821115614888576148876147f2565b5b602082029050602081019050919050565b60006148ac6148a78461486d565b614852565b905080838252602082019050602084028301858111156148cf576148ce6144f6565b5b835b818110156148f857806148e4888261419e565b8452602084019350506020810190506148d1565b5050509392505050565b600082601f830112614917576149166144ec565b5b8135614927848260208601614899565b91505092915050565b60006020828403121561494657614945614173565b5b600082013567ffffffffffffffff81111561496457614963614178565b5b61497084828501614902565b91505092915050565b600080604083850312156149905761498f614173565b5b600061499e8582860161439f565b92505060206149af8582860161439f565b9150509250929050565b6000806000606084860312156149d2576149d1614173565b5b60006149e08682870161439f565b93505060206149f18682870161439f565b9250506040614a028682870161419e565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a468261417d565b9150614a518361417d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614a8a57614a89614a0c565b5b828202905092915050565b6000614aa08261417d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ad257614ad1614a0c565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732e00000000000000600082015250565b6000614b53601983614b0c565b9150614b5e82614b1d565b602082019050919050565b60006020820190508181036000830152614b8281614b46565b9050919050565b6000614b948261417d565b9150614b9f8361417d565b9250828201905080821115614bb757614bb6614a0c565b5b92915050565b6000606082019050614bd2600083018661435e565b614bdf602083018561435e565b614bec6040830184614764565b949350505050565b6000614bff8261417d565b915060008203614c1257614c11614a0c565b5b600182039050919050565b6000614c288261417d565b9150614c338361417d565b9250828203905081811115614c4b57614c4a614a0c565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614c8b8261417d565b9150614c968361417d565b925082614ca657614ca5614c51565b5b828204905092915050565b6000604082019050614cc6600083018561435e565b614cd36020830184614764565b9392505050565b60008160601b9050919050565b6000614cf282614cda565b9050919050565b6000614d0482614ce7565b9050919050565b614d1c614d178261420f565b614cf9565b82525050565b6000614d2e8285614d0b565b601482019150614d3e8284614d0b565b6014820191508190509392505050565b6000819050919050565b614d69614d648261417d565b614d4e565b82525050565b6000614d7b8285614d58565b602082019150614d8b8284614d0b565b601482019150819050939250505056fea264697066735822122057d230393a932febfaacac97af53a0cc27e1b2eb184f5d892afb95c4114f2f0264736f6c63430008100033
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80636da42a15116100a25780638da5cb5b116100715780638da5cb5b1461032a5780639435298b14610348578063af640d0f14610378578063b55fb57414610396578063e0a31339146103c65761010b565b80636da42a151461026a57806375b024051461029a5780637e9da7a2146102ca578063809741ed146102fa5761010b565b8063334503bf116100de578063334503bf146101aa57806336511013146101da57806347402bea1461020a5780635eb2088e1461023a5761010b565b80630e0578f514610110578063127e11971461014057806318df23881461015e578063299821f61461018e575b600080fd5b61012a600480360381019061012591906141b3565b6103f6565b6040516101379190614342565b60405180910390f35b6101486105a6565b604051610155919061436d565b60405180910390f35b610178600480360381019061017391906143b4565b6105be565b60405161018591906144ca565b60405180910390f35b6101a860048036038101906101a39190614551565b610769565b005b6101c460048036038101906101bf919061459e565b61096b565b6040516101d191906144ca565b60405180910390f35b6101f460048036038101906101ef9190614619565b610c42565b60405161020191906144ca565b60405180910390f35b610224600480360381019061021f9190614685565b611112565b6040516102319190614773565b60405180910390f35b610254600480360381019061024f919061478e565b611dfc565b60405161026191906144ca565b60405180910390f35b610284600480360381019061027f91906141b3565b61225a565b60405161029191906144ca565b60405180910390f35b6102b460048036038101906102af9190614930565b61241d565b6040516102c191906144ca565b60405180910390f35b6102e460048036038101906102df919061459e565b612628565b6040516102f191906144ca565b60405180910390f35b610314600480360381019061030f9190614979565b6128ff565b60405161032191906144ca565b60405180910390f35b610332612c10565b60405161033f919061436d565b60405180910390f35b610362600480360381019061035d91906149b9565b612c36565b60405161036f91906144ca565b60405180910390f35b610380612df4565b60405161038d9190614773565b60405180910390f35b6103b060048036038101906103ab9190614930565b612dfa565b6040516103bd91906144ca565b60405180910390f35b6103e060048036038101906103db919061459e565b61310c565b6040516103ed91906144ca565b60405180910390f35b6103fe614050565b6006600083815260200190815260200160002060405180610180016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016008820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160149054906101000a900460ff1660ff1660ff1681526020016009820160159054906101000a900460ff1660ff1660ff16815250509050919050565b735cec09f125f4839656164a5109bc076daabd6ed681565b606060006105ce8686600061327d565b90506000600160008381526020019081526020016000206000868152602001908152602001600020600001541161062c576001600082815260200190815260200160002060008081526020019081526020016000206002015461062e565b835b93506000806002856106409190614a3b565b67ffffffffffffffff811115610659576106586147f2565b5b6040519080825280602002602001820160405280156106875781602001602082028036833780820191505090505b50905060005b8581101561075a57600087031561075a57868284806106ab90614a95565b9550815181106106be576106bd614add565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600001548284806106fe90614a95565b95508151811061071157610710614add565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600201549650808061075290614a95565b91505061068d565b50809350505050949350505050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f090614b69565b60405180910390fd5b60005b82829050811015610966576008600660008585858181106108205761081f614add565b5b90506020020135815260200190815260200160002060090160159054906101000a900460ff1660ff1603610953576006600084848481811061086557610864614add565b5b9050602002013581526020019081526020016000206000808201600090556001820160009055600282016000905560038201600090556004820160009055600582016000905560068201600090556007820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160146101000a81549060ff02191690556009820160156101000a81549060ff021916905550505b808061095e90614a95565b9150506107fc565b505050565b6060600061097a878787613300565b905060036000828152602001908152602001600020600085815260200190815260200160002060010154935060008403610a0057600167ffffffffffffffff8111156109c9576109c86147f2565b5b6040519080825280602002602001820160405280156109f75781602001602082028036833780820191505090505b50915050610c39565b600080600685610a109190614a3b565b67ffffffffffffffff811115610a2957610a286147f2565b5b604051908082528060200260200182016040528015610a575781602001602082028036833780820191505090505b50905060005b85811015610c31576000870315610c315786828480610a7b90614a95565b955081518110610a8e57610a8d614add565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff16828480610acd90614a95565b955081518110610ae057610adf614add565b5b6020026020010181815250506006600088815260200190815260200160002060000154828480610b0f90614a95565b955081518110610b2257610b21614add565b5b6020026020010181815250506006600088815260200190815260200160002060030154828480610b5190614a95565b955081518110610b6457610b63614add565b5b6020026020010181815250506006600088815260200190815260200160002060020154828480610b9390614a95565b955081518110610ba657610ba5614add565b5b6020026020010181815250506006600088815260200190815260200160002060040154828480610bd590614a95565b955081518110610be857610be7614add565b5b6020026020010181815250506003600085815260200190815260200160002060008881526020019081526020016000206001015496508080610c2990614a95565b915050610a5d565b508093505050505b95945050505050565b60606000600467ffffffffffffffff811115610c6157610c606147f2565b5b604051908082528060200260200182016040528015610c8f5781602001602082028036833780820191505090505b5090506000806000806000600660008a815260200190815260200160002060090160159054906101000a900460ff1690506000600660008a815260200190815260200160002060090160159054906101000a900460ff16905060008260ff161115610d6f57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008c815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168095508197505050610de6565b600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1680955081975050505b60018260ff161480610dfb575060068260ff16145b80610e09575060078260ff16145b80610e17575060098260ff16145b15610f1c57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610ed257600660008b81526020019081526020016000206002015485610ea79190614b89565b9450600660008b81526020019081526020016000206006015483610ecb9190614b89565b9250610f1b565b600660008b81526020019081526020016000206002015483610ef49190614b89565b9250600660008b81526020019081526020016000206006015485610f189190614b89565b94505b5b60018160ff161480610f31575060068160ff16145b80610f3f575060078160ff16145b80610f4d575060098160ff16145b1561105257600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff160361100857600660008a81526020019081526020016000206002015485610fdd9190614b89565b9450600660008a815260200190815260200160002060060154836110019190614b89565b9250611051565b600660008a8152602001908152602001600020600201548361102a9190614b89565b9250600660008a8152602001908152602001600020600601548561104e9190614b89565b94505b5b8573ffffffffffffffffffffffffffffffffffffffff168760008151811061107d5761107c614add565b5b602002602001018181525050848760018151811061109e5761109d614add565b5b6020026020010181815250508373ffffffffffffffffffffffffffffffffffffffff16876002815181106110d5576110d4614add565b5b60200260200101818152505082876003815181106110f6576110f5614add565b5b6020026020010181815250508697505050505050505092915050565b6000735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461116057600080fd5b611168614050565b4281600001818152505089816040018181525050878160800181815250508681610140019060ff16908160ff1681525050858160600181815250508a8160e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508881610100019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508b81610120019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181610160019060ff16908160ff1681525050600080815461126f90614a95565b91905081905550600080549050600061129561128d8e8d600061327d565b888a8c613347565b80925081985050508015611bd5576112ab6140f9565b6112b78c8f600061327d565b81600001818152505060016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250505b600081602001511115611a0f5760016000826000015181526020019081526020016000206000826020015181526020019081526020016000206000015481604001818152505060018a60ff16036113575780604001518911611a0f57611363565b80604001518910611a0f575b6000860361141057600984610160019060ff16908160ff1681525050735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128f86610120015187604001516040518463ffffffff1660e01b81526004016113d993929190614bbd565b600060405180830381600087803b1580156113f357600080fd5b505af1158015611407573d6000803e3d6000fd5b50505050611a0f565b8561141a90614bf4565b9550600660008260200151815260200190815260200160002060040154816060018181525050806060015184604001511061145957806060015161145f565b83604001515b81608001818152505083604001518460800151826080015186604001516114869190614c1d565b6114909190614a3b565b61149a9190614c80565b84608001818152505060008460800151146114b95780608001516114bf565b83604001515b8160a00181815250508060a00151846040018181516114de9190614c1d565b915081815250508060a001518460a0018181516114fb9190614b89565b9150818152505068056bc75e2d63100000878260a0015161151c9190614a3b565b6115269190614c80565b8160c00181815250508060c0015181610100018181516115469190614b89565b91508181525050600660008260200151815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681610140019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128f8361014001518460c001518560a0015161160b9190614c1d565b6040518463ffffffff1660e01b815260040161162993929190614bbd565b600060405180830381600087803b15801561164357600080fd5b505af1158015611657573d6000803e3d6000fd5b505050508060c001518160a0015161166f9190614c1d565b600660008360200151815260200190815260200160002060060160008282546116989190614b89565b925050819055508060c00151600660008360200151815260200190815260200160002060010160008282546116cd9190614b89565b92505081905550806060015160066000836020015181526020019081526020016000206002015482608001516117039190614a3b565b61170d9190614c80565b8160a001818152505068056bc75e2d63100000878260a001516117309190614a3b565b61173a9190614c80565b8160c00181815250508060a00151600660008360200151815260200190815260200160002060020160008282546117719190614c1d565b925050819055508060800151816060015161178c9190614c1d565b6006600083602001518152602001908152602001600020600401819055508060a00151600660008360200151815260200190815260200160002060050160008282546117d89190614b89565b925050819055508060c0015181610120018181516117f69190614b89565b915081815250508060c001518160a001516118119190614c1d565b8160e0018181516118229190614b89565b915081815250508060c001518160a0015161183d9190614c1d565b8460c00181815161184e9190614b89565b915081815250508060c001518460200181815161186b9190614b89565b915081815250504260066000836020015181526020019081526020016000206000018190555080602001517f271adf7ca5026da9466c7e2ee50294432b6518106821bb0baa27adfbe5203bad60405160405180910390a260006006600083602001518152602001908152602001600020600201540361199d576007600660008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061192a81600001518260200151613726565b61193f8c8f836101400151846020015161381b565b6119548c8f8361014001518460200151613ad9565b6119638c8f8360200151613ba0565b60016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250506119d1565b60068060008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055505b60008460400151036119f657600784610160019060ff16908160ff1681525050611a0f565b600684610160019060ff16908160ff16815250506112f6565b60008160e001511115611aa957735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128d8661012001518460e001516040518463ffffffff1660e01b8152600401611a7693929190614bbd565b600060405180830381600087803b158015611a9057600080fd5b505af1158015611aa4573d6000803e3d6000fd5b505050505b60008161010001511115611b3e57735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663fd9be5228f8361010001516040518363ffffffff1660e01b8152600401611b0b929190614cb1565b600060405180830381600087803b158015611b2557600080fd5b505af1158015611b39573d6000803e3d6000fd5b505050505b60008161012001511115611bd357735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663fd9be5228d8361012001516040518363ffffffff1660e01b8152600401611ba0929190614cb1565b600060405180830381600087803b158015611bba57600080fd5b505af1158015611bce573d6000803e3d6000fd5b505050505b505b8260066000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101008201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160090160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101408201518160090160146101000a81548160ff021916908360ff1602179055506101608201518160090160156101000a81548160ff021916908360ff160217905550905050600183610160015160ff161480611d6c5750600683610160015160ff16145b15611d9e57611d88611d808e8d600061327d565b88848b613c53565b611d998d8c85610120015185613d3e565b611dbb565b611daf8d8c85610120015185613ad9565b611dba8d8c84613ba0565b5b817f2f539bcf68b0eef24f9fef1ae5ad7dd5a37f80a2fab34f406ad2b92c779d606460405160405180910390a28193505050509a9950505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154925060008303611ead57600167ffffffffffffffff811115611e7757611e766147f2565b5b604051908082528060200260200182016040528015611ea55781602001602082028036833780820191505090505b509050612253565b600080600984611ebd9190614a3b565b67ffffffffffffffff811115611ed657611ed56147f2565b5b604051908082528060200260200182016040528015611f045781602001602082028036833780820191505090505b50905060005b8481101561224c57600086031561224c5785828480611f2890614a95565b955081518110611f3b57611f3a614add565b5b6020026020010181815250506006600087815260200190815260200160002060000154828480611f6a90614a95565b955081518110611f7d57611f7c614add565b5b6020026020010181815250506006600087815260200190815260200160002060030154828480611fac90614a95565b955081518110611fbf57611fbe614add565b5b6020026020010181815250506006600087815260200190815260200160002060020154828480611fee90614a95565b95508151811061200157612000614add565b5b6020026020010181815250506006600087815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061206690614a95565b95508151811061207957612078614add565b5b60200260200101818152505060066000878152602001908152602001600020600401548284806120a890614a95565b9550815181106120bb576120ba614add565b5b6020026020010181815250506006600087815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061212090614a95565b95508151811061213357612132614add565b5b6020026020010181815250506006600087815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061217290614a95565b95508151811061218557612184614add565b5b6020026020010181815250506006600087815260200190815260200160002060090160159054906101000a900460ff1660ff168284806121c490614a95565b9550815181106121d7576121d6614add565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600101549550808061224490614a95565b915050611f0a565b5080925050505b9392505050565b60606000600667ffffffffffffffff811115612279576122786147f2565b5b6040519080825280602002602001820160405280156122a75781602001602082028036833780820191505090505b5090506006600084815260200190815260200160002060090160159054906101000a900460ff1660ff16816000815181106122e5576122e4614add565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff168160018151811061232c5761232b614add565b5b60200260200101818152505060066000848152602001908152602001600020600201548160028151811061236357612362614add565b5b60200260200101818152505060066000848152602001908152602001600020600401548160038151811061239a57612399614add565b5b6020026020010181815250506006600084815260200190815260200160002060050154816004815181106123d1576123d0614add565b5b60200260200101818152505060066000848152602001908152602001600020600601548160058151811061240857612407614add565b5b60200260200101818152505080915050919050565b606060008060005b845181101561261d5784818151811061244157612440614add565b5b602002602001015191506006600083815260200190815260200160002060090160159054906101000a900460ff1692503373ffffffffffffffffffffffffffffffffffffffff166006600084815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612501575060048360ff1614806124f2575060078360ff16145b80612500575060098360ff16145b5b156125e8576125866125806006600085815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633613300565b83613f63565b60086006600084815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550817fbd000546857b596b03c884060c13e7d8c7a7ce52366d2f116f76688e6f000f6660405160405180910390a261260a565b60008582815181106125fd576125fc614add565b5b6020026020010181815250505b808061261590614a95565b915050612425565b508392505050919050565b60606000612637878787613300565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036126bd57600167ffffffffffffffff811115612686576126856147f2565b5b6040519080825280602002602001820160405280156126b45781602001602082028036833780820191505090505b509150506128f6565b6000806006856126cd9190614a3b565b67ffffffffffffffff8111156126e6576126e56147f2565b5b6040519080825280602002602001820160405280156127145781602001602082028036833780820191505090505b50905060005b858110156128ee5760008703156128ee578682848061273890614a95565b95508151811061274b5761274a614add565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061278a90614a95565b95508151811061279d5761279c614add565b5b60200260200101818152505060066000888152602001908152602001600020600001548284806127cc90614a95565b9550815181106127df576127de614add565b5b602002602001018181525050600660008881526020019081526020016000206003015482848061280e90614a95565b95508151811061282157612820614add565b5b602002602001018181525050600660008881526020019081526020016000206005015482848061285090614a95565b95508151811061286357612862614add565b5b602002602001018181525050600660008881526020019081526020016000206006015482848061289290614a95565b9550815181106128a5576128a4614add565b5b60200260200101818152505060046000858152602001908152602001600020600088815260200190815260200160002060010154965080806128e690614a95565b91505061271a565b508093505050505b95945050505050565b6060600061290f8484600161327d565b905060006005600083815260200190815260200160002060006033811061293957612938614add565b5b015490506000810361299857600167ffffffffffffffff8111156129605761295f6147f2565b5b60405190808252806020026020018201604052801561298e5781602001602082028036833780820191505090505b5092505050612c0a565b600080600061012c67ffffffffffffffff8111156129b9576129b86147f2565b5b6040519080825280602002602001820160405280156129e75781602001602082028036833780820191505090505b50905060005b6032811015612c0057600560008781526020019081526020016000208560338110612a1b57612a1a614add565b5b0154925082828580612a2c90614a95565b965081518110612a3f57612a3e614add565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff16828580612a7e90614a95565b965081518110612a9157612a90614add565b5b6020026020010181815250506006600084815260200190815260200160002060000154828580612ac090614a95565b965081518110612ad357612ad2614add565b5b6020026020010181815250506006600084815260200190815260200160002060030154828580612b0290614a95565b965081518110612b1557612b14614add565b5b6020026020010181815250506006600084815260200190815260200160002060050154828580612b4490614a95565b965081518110612b5757612b56614add565b5b6020026020010181815250506006600084815260200190815260200160002060060154828580612b8690614a95565b965081518110612b9957612b98614add565b5b602002602001018181525050600085612bb190614bf4565b95508503612bed57603294506000600560008881526020019081526020016000208660338110612be457612be3614add565b5b01540315612c00575b8080612bf890614a95565b9150506129ed565b5080955050505050505b92915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606000612c468585600061327d565b90506000806001600084815260200190815260200160002060008081526020019081526020016000206002015490506000600386612c849190614a3b565b67ffffffffffffffff811115612c9d57612c9c6147f2565b5b604051908082528060200260200182016040528015612ccb5781602001602082028036833780820191505090505b50905060005b86811015612de5576000830315612de5576006600084815260200190815260200160002060030154828580612d0590614a95565b965081518110612d1857612d17614add565b5b6020026020010181815250506006600084815260200190815260200160002060020154828580612d4790614a95565b965081518110612d5a57612d59614add565b5b6020026020010181815250506006600084815260200190815260200160002060040154828580612d8990614a95565b965081518110612d9c57612d9b614add565b5b6020026020010181815250506001600086815260200190815260200160002060008481526020019081526020016000206002015492508080612ddd90614a95565b915050612cd1565b50809450505050509392505050565b60005481565b60606000806000806000805b87518110156130fe57878181518110612e2257612e21614add565b5b602002602001015194506006600086815260200190815260200160002060090160159054906101000a900460ff1695503373ffffffffffffffffffffffffffffffffffffffff166006600087815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612ed4575060018660ff161480612ed3575060068660ff16145b5b156130c957600660008681526020019081526020016000206002015493506006600086815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692506006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff1663d9caed128433876040518463ffffffff1660e01b8152600401612fb593929190614bbd565b600060405180830381600087803b158015612fcf57600080fd5b505af1158015612fe3573d6000803e3d6000fd5b50505050426006600087815260200190815260200160002060000181905550600060066000878152602001908152602001600020600201819055506000600660008781526020019081526020016000206004018190555060046006600087815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061307f6130798484600061327d565b86613726565b61308b8383338861381b565b61309783833388613ad9565b847f935c9ad2f1fda9d7eae0d2a512f1521cb7190ee06165414e722366a65975fb6b60405160405180910390a26130eb565b60008882815181106130de576130dd614add565b5b6020026020010181815250505b80806130f690614a95565b915050612e06565b508695505050505050919050565b6060600061311b878787613300565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036131a157600167ffffffffffffffff81111561316a576131696147f2565b5b6040519080825280602002602001820160405280156131985781602001602082028036833780820191505090505b50915050613274565b6000808467ffffffffffffffff8111156131be576131bd6147f2565b5b6040519080825280602002602001820160405280156131ec5781602001602082028036833780820191505090505b50905060005b8581101561326c57600087031561326c578682848061321090614a95565b95508151811061322357613222614add565b5b602002602001018181525050600460008581526020019081526020016000206000888152602001908152602001600020600101549650808061326490614a95565b9150506131f2565b508093505050505b95945050505050565b600081156132cb578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16106132bf5782846132c2565b83835b80945081955050505b83836040516020016132de929190614d22565b6040516020818303038152906040528051906020012060001c90509392505050565b60008061330f8585600161327d565b90508083604051602001613324929190614d6f565b6040516020818303038152906040528051906020012060001c9150509392505050565b6000806000806000600160008a8152602001908152602001600020600089815260200190815260200160002060000154116133a957600160008981526020019081526020016000206000808152602001908152602001600020600201546133ab565b865b9650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600082036133ee576000600193509350505061371d565b60018560ff160361358d57818610156134db576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b818610156134a6576000810361344a5786600193509350505061371d565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060010154905061342c565b60016000898152602001908152602001600020600088815260200190815260200160002060020154600093509350505061371d565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861061357f57600081036135235760008093509350505061371d565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600201549050613506565b86600093509350505061371d565b8186111561366f576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b8186111561363a57600081036135de5786600193509350505061371d565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206001015490506135c0565b60016000898152602001908152602001600020600088815260200190815260200160002060020154600093509350505061371d565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861161371357600081036136b75760008093509350505061371d565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060020154905061369a565b8660009350935050505b94509492505050565b600060016000848152602001908152602001600020600083815260200190815260200160002060010154905060006001600085815260200190815260200160002060008481526020019081526020016000206002015490508160016000868152602001908152602001600020600083815260200190815260200160002060010181905550806001600086815260200190815260200160002060008481526020019081526020016000206002018190555060016000858152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505060006139eb878787613300565b9050600360008281526020019081526020016000206000858152602001908152602001600020600001549250600360008281526020019081526020016000206000858152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555081600360008381526020019081526020016000206000858152602001908152602001600020600101819055506003600082815260200190815260200160002060008581526020019081526020016000206000808201600090556001820160009055505050505050505050565b6000613ae6858585613300565b90506000600460008381526020019081526020016000206000808152602001908152602001600020600101549050826004600084815260200190815260200160002060008381526020019081526020016000206000018190555082600460008481526020019081526020016000206000808152602001908152602001600020600101819055508060046000848152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b6000613bae8484600161327d565b9050600060056000838152602001908152602001600020600060338110613bd857613bd7614add565b5b0154905060328103613be957600090505b80613bf390614a95565b905082600560008481526020019081526020016000208260338110613c1b57613c1a614add565b5b01819055508060056000848152602001908152602001600020600060338110613c4757613c46614add565b5b01819055505050505050565b6000600160008681526020019081526020016000206000858152602001908152602001600020600101549050826001600087815260200190815260200160002060008681526020019081526020016000206001018190555082600160008781526020019081526020016000206000838152602001908152602001600020600201819055506040518060600160405280838152602001828152602001858152506001600087815260200190815260200160002060008581526020019081526020016000206000820151816000015560208201518160010155604082015181600201559050505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060010154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206001018190555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101819055506000613eab868686613300565b9050600360008281526020019081526020016000206000808152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555082600360008381526020019081526020016000206000808152602001908152602001600020600101819055508160036000838152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006004600084815260200190815260200160002060008381526020019081526020016000206000015490506000600460008581526020019081526020016000206000848152602001908152602001600020600101549050816004600086815260200190815260200160002060008381526020019081526020016000206000018190555080600460008681526020019081526020016000206000848152602001908152602001600020600101819055506004600085815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505050505050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6141908161417d565b811461419b57600080fd5b50565b6000813590506141ad81614187565b92915050565b6000602082840312156141c9576141c8614173565b5b60006141d78482850161419e565b91505092915050565b6141e98161417d565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061421a826141ef565b9050919050565b61422a8161420f565b82525050565b600060ff82169050919050565b61424681614230565b82525050565b6101808201600082015161426360008501826141e0565b50602082015161427660208501826141e0565b50604082015161428960408501826141e0565b50606082015161429c60608501826141e0565b5060808201516142af60808501826141e0565b5060a08201516142c260a08501826141e0565b5060c08201516142d560c08501826141e0565b5060e08201516142e860e0850182614221565b506101008201516142fd610100850182614221565b50610120820151614312610120850182614221565b5061014082015161432761014085018261423d565b5061016082015161433c61016085018261423d565b50505050565b600061018082019050614358600083018461424c565b92915050565b6143678161420f565b82525050565b6000602082019050614382600083018461435e565b92915050565b6143918161420f565b811461439c57600080fd5b50565b6000813590506143ae81614388565b92915050565b600080600080608085870312156143ce576143cd614173565b5b60006143dc8782880161439f565b94505060206143ed8782880161439f565b93505060406143fe8782880161419e565b925050606061440f8782880161419e565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061445383836141e0565b60208301905092915050565b6000602082019050919050565b60006144778261441b565b6144818185614426565b935061448c83614437565b8060005b838110156144bd5781516144a48882614447565b97506144af8361445f565b925050600181019050614490565b5085935050505092915050565b600060208201905081810360008301526144e4818461446c565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112614511576145106144ec565b5b8235905067ffffffffffffffff81111561452e5761452d6144f1565b5b60208301915083602082028301111561454a576145496144f6565b5b9250929050565b6000806020838503121561456857614567614173565b5b600083013567ffffffffffffffff81111561458657614585614178565b5b614592858286016144fb565b92509250509250929050565b600080600080600060a086880312156145ba576145b9614173565b5b60006145c88882890161439f565b95505060206145d98882890161439f565b94505060406145ea8882890161439f565b93505060606145fb8882890161419e565b925050608061460c8882890161419e565b9150509295509295909350565b600080604083850312156146305761462f614173565b5b600061463e8582860161419e565b925050602061464f8582860161419e565b9150509250929050565b61466281614230565b811461466d57600080fd5b50565b60008135905061467f81614659565b92915050565b6000806000806000806000806000806101408b8d0312156146a9576146a8614173565b5b60006146b78d828e0161439f565b9a505060206146c88d828e0161439f565b99505060406146d98d828e0161419e565b98505060606146ea8d828e0161439f565b97505060806146fb8d828e0161419e565b96505060a061470c8d828e01614670565b95505060c061471d8d828e0161419e565b94505060e061472e8d828e0161419e565b9350506101006147408d828e0161419e565b9250506101206147528d828e0161419e565b9150509295989b9194979a5092959850565b61476d8161417d565b82525050565b60006020820190506147886000830184614764565b92915050565b6000806000606084860312156147a7576147a6614173565b5b60006147b58682870161439f565b93505060206147c68682870161419e565b92505060406147d78682870161419e565b9150509250925092565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61482a826147e1565b810181811067ffffffffffffffff82111715614849576148486147f2565b5b80604052505050565b600061485c614169565b90506148688282614821565b919050565b600067ffffffffffffffff821115614888576148876147f2565b5b602082029050602081019050919050565b60006148ac6148a78461486d565b614852565b905080838252602082019050602084028301858111156148cf576148ce6144f6565b5b835b818110156148f857806148e4888261419e565b8452602084019350506020810190506148d1565b5050509392505050565b600082601f830112614917576149166144ec565b5b8135614927848260208601614899565b91505092915050565b60006020828403121561494657614945614173565b5b600082013567ffffffffffffffff81111561496457614963614178565b5b61497084828501614902565b91505092915050565b600080604083850312156149905761498f614173565b5b600061499e8582860161439f565b92505060206149af8582860161439f565b9150509250929050565b6000806000606084860312156149d2576149d1614173565b5b60006149e08682870161439f565b93505060206149f18682870161439f565b9250506040614a028682870161419e565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a468261417d565b9150614a518361417d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614a8a57614a89614a0c565b5b828202905092915050565b6000614aa08261417d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ad257614ad1614a0c565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732e00000000000000600082015250565b6000614b53601983614b0c565b9150614b5e82614b1d565b602082019050919050565b60006020820190508181036000830152614b8281614b46565b9050919050565b6000614b948261417d565b9150614b9f8361417d565b9250828201905080821115614bb757614bb6614a0c565b5b92915050565b6000606082019050614bd2600083018661435e565b614bdf602083018561435e565b614bec6040830184614764565b949350505050565b6000614bff8261417d565b915060008203614c1257614c11614a0c565b5b600182039050919050565b6000614c288261417d565b9150614c338361417d565b9250828203905081811115614c4b57614c4a614a0c565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614c8b8261417d565b9150614c968361417d565b925082614ca657614ca5614c51565b5b828204905092915050565b6000604082019050614cc6600083018561435e565b614cd36020830184614764565b9392505050565b60008160601b9050919050565b6000614cf282614cda565b9050919050565b6000614d0482614ce7565b9050919050565b614d1c614d178261420f565b614cf9565b82525050565b6000614d2e8285614d0b565b601482019150614d3e8284614d0b565b6014820191508190509392505050565b6000819050919050565b614d69614d648261417d565b614d4e565b82525050565b6000614d7b8285614d58565b602082019150614d8b8284614d0b565b601482019150819050939250505056fea264697066735822122057d230393a932febfaacac97af53a0cc27e1b2eb184f5d892afb95c4114f2f0264736f6c63430008100033