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:25.397356Z
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 = 0xC36755F64E372870Ede6f02360495e0f55C3E0E7; // Контракт с депозитами 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[](7); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия] 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; result[6] = orders[_id].commission; 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
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50614e08806100756000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80636da42a15116100a25780638da5cb5b116100715780638da5cb5b1461032a5780639435298b14610348578063af640d0f14610378578063b55fb57414610396578063e0a31339146103c65761010b565b80636da42a151461026a57806375b024051461029a5780637e9da7a2146102ca578063809741ed146102fa5761010b565b8063334503bf116100de578063334503bf146101aa57806336511013146101da57806347402bea1461020a5780635eb2088e1461023a5761010b565b80630e0578f514610110578063127e11971461014057806318df23881461015e578063299821f61461018e575b600080fd5b61012a600480360381019061012591906141ea565b6103f6565b6040516101379190614379565b60405180910390f35b6101486105a6565b60405161015591906143a4565b60405180910390f35b610178600480360381019061017391906143eb565b6105be565b6040516101859190614501565b60405180910390f35b6101a860048036038101906101a39190614588565b610769565b005b6101c460048036038101906101bf91906145d5565b61096b565b6040516101d19190614501565b60405180910390f35b6101f460048036038101906101ef9190614650565b610c42565b6040516102019190614501565b60405180910390f35b610224600480360381019061021f91906146bc565b611112565b60405161023191906147aa565b60405180910390f35b610254600480360381019061024f91906147c5565b611dfc565b6040516102619190614501565b60405180910390f35b610284600480360381019061027f91906141ea565b61225a565b6040516102919190614501565b60405180910390f35b6102b460048036038101906102af9190614967565b612454565b6040516102c19190614501565b60405180910390f35b6102e460048036038101906102df91906145d5565b61265f565b6040516102f19190614501565b60405180910390f35b610314600480360381019061030f91906149b0565b612936565b6040516103219190614501565b60405180910390f35b610332612c47565b60405161033f91906143a4565b60405180910390f35b610362600480360381019061035d91906149f0565b612c6d565b60405161036f9190614501565b60405180910390f35b610380612e2b565b60405161038d91906147aa565b60405180910390f35b6103b060048036038101906103ab9190614967565b612e31565b6040516103bd9190614501565b60405180910390f35b6103e060048036038101906103db91906145d5565b613143565b6040516103ed9190614501565b60405180910390f35b6103fe614087565b6006600083815260200190815260200160002060405180610180016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016008820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160149054906101000a900460ff1660ff1660ff1681526020016009820160159054906101000a900460ff1660ff1660ff16815250509050919050565b73c36755f64e372870ede6f02360495e0f55c3e0e781565b606060006105ce868660006132b4565b90506000600160008381526020019081526020016000206000868152602001908152602001600020600001541161062c576001600082815260200190815260200160002060008081526020019081526020016000206002015461062e565b835b93506000806002856106409190614a72565b67ffffffffffffffff81111561065957610658614829565b5b6040519080825280602002602001820160405280156106875781602001602082028036833780820191505090505b50905060005b8581101561075a57600087031561075a57868284806106ab90614acc565b9550815181106106be576106bd614b14565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600001548284806106fe90614acc565b95508151811061071157610710614b14565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600201549650808061075290614acc565b91505061068d565b50809350505050949350505050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f090614ba0565b60405180910390fd5b60005b82829050811015610966576008600660008585858181106108205761081f614b14565b5b90506020020135815260200190815260200160002060090160159054906101000a900460ff1660ff1603610953576006600084848481811061086557610864614b14565b5b9050602002013581526020019081526020016000206000808201600090556001820160009055600282016000905560038201600090556004820160009055600582016000905560068201600090556007820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160146101000a81549060ff02191690556009820160156101000a81549060ff021916905550505b808061095e90614acc565b9150506107fc565b505050565b6060600061097a878787613337565b905060036000828152602001908152602001600020600085815260200190815260200160002060010154935060008403610a0057600167ffffffffffffffff8111156109c9576109c8614829565b5b6040519080825280602002602001820160405280156109f75781602001602082028036833780820191505090505b50915050610c39565b600080600685610a109190614a72565b67ffffffffffffffff811115610a2957610a28614829565b5b604051908082528060200260200182016040528015610a575781602001602082028036833780820191505090505b50905060005b85811015610c31576000870315610c315786828480610a7b90614acc565b955081518110610a8e57610a8d614b14565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff16828480610acd90614acc565b955081518110610ae057610adf614b14565b5b6020026020010181815250506006600088815260200190815260200160002060000154828480610b0f90614acc565b955081518110610b2257610b21614b14565b5b6020026020010181815250506006600088815260200190815260200160002060030154828480610b5190614acc565b955081518110610b6457610b63614b14565b5b6020026020010181815250506006600088815260200190815260200160002060020154828480610b9390614acc565b955081518110610ba657610ba5614b14565b5b6020026020010181815250506006600088815260200190815260200160002060040154828480610bd590614acc565b955081518110610be857610be7614b14565b5b6020026020010181815250506003600085815260200190815260200160002060008881526020019081526020016000206001015496508080610c2990614acc565b915050610a5d565b508093505050505b95945050505050565b60606000600467ffffffffffffffff811115610c6157610c60614829565b5b604051908082528060200260200182016040528015610c8f5781602001602082028036833780820191505090505b5090506000806000806000600660008a815260200190815260200160002060090160159054906101000a900460ff1690506000600660008a815260200190815260200160002060090160159054906101000a900460ff16905060008260ff161115610d6f57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008c815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168095508197505050610de6565b600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1680955081975050505b60018260ff161480610dfb575060068260ff16145b80610e09575060078260ff16145b80610e17575060098260ff16145b15610f1c57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610ed257600660008b81526020019081526020016000206002015485610ea79190614bc0565b9450600660008b81526020019081526020016000206006015483610ecb9190614bc0565b9250610f1b565b600660008b81526020019081526020016000206002015483610ef49190614bc0565b9250600660008b81526020019081526020016000206006015485610f189190614bc0565b94505b5b60018160ff161480610f31575060068160ff16145b80610f3f575060078160ff16145b80610f4d575060098160ff16145b1561105257600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff160361100857600660008a81526020019081526020016000206002015485610fdd9190614bc0565b9450600660008a815260200190815260200160002060060154836110019190614bc0565b9250611051565b600660008a8152602001908152602001600020600201548361102a9190614bc0565b9250600660008a8152602001908152602001600020600601548561104e9190614bc0565b94505b5b8573ffffffffffffffffffffffffffffffffffffffff168760008151811061107d5761107c614b14565b5b602002602001018181525050848760018151811061109e5761109d614b14565b5b6020026020010181815250508373ffffffffffffffffffffffffffffffffffffffff16876002815181106110d5576110d4614b14565b5b60200260200101818152505082876003815181106110f6576110f5614b14565b5b6020026020010181815250508697505050505050505092915050565b600073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461116057600080fd5b611168614087565b4281600001818152505089816040018181525050878160800181815250508681610140019060ff16908160ff1681525050858160600181815250508a8160e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508881610100019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508b81610120019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181610160019060ff16908160ff1681525050600080815461126f90614acc565b91905081905550600080549050600061129561128d8e8d60006132b4565b888a8c61337e565b80925081985050508015611bd5576112ab614130565b6112b78c8f60006132b4565b81600001818152505060016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250505b600081602001511115611a0f5760016000826000015181526020019081526020016000206000826020015181526020019081526020016000206000015481604001818152505060018a60ff16036113575780604001518911611a0f57611363565b80604001518910611a0f575b6000860361141057600984610160019060ff16908160ff168152505073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128f86610120015187604001516040518463ffffffff1660e01b81526004016113d993929190614bf4565b600060405180830381600087803b1580156113f357600080fd5b505af1158015611407573d6000803e3d6000fd5b50505050611a0f565b8561141a90614c2b565b9550600660008260200151815260200190815260200160002060040154816060018181525050806060015184604001511061145957806060015161145f565b83604001515b81608001818152505083604001518460800151826080015186604001516114869190614c54565b6114909190614a72565b61149a9190614cb7565b84608001818152505060008460800151146114b95780608001516114bf565b83604001515b8160a00181815250508060a00151846040018181516114de9190614c54565b915081815250508060a001518460a0018181516114fb9190614bc0565b9150818152505068056bc75e2d63100000878260a0015161151c9190614a72565b6115269190614cb7565b8160c00181815250508060c0015181610100018181516115469190614bc0565b91508181525050600660008260200151815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681610140019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128f8361014001518460c001518560a0015161160b9190614c54565b6040518463ffffffff1660e01b815260040161162993929190614bf4565b600060405180830381600087803b15801561164357600080fd5b505af1158015611657573d6000803e3d6000fd5b505050508060c001518160a0015161166f9190614c54565b600660008360200151815260200190815260200160002060060160008282546116989190614bc0565b925050819055508060c00151600660008360200151815260200190815260200160002060010160008282546116cd9190614bc0565b92505081905550806060015160066000836020015181526020019081526020016000206002015482608001516117039190614a72565b61170d9190614cb7565b8160a001818152505068056bc75e2d63100000878260a001516117309190614a72565b61173a9190614cb7565b8160c00181815250508060a00151600660008360200151815260200190815260200160002060020160008282546117719190614c54565b925050819055508060800151816060015161178c9190614c54565b6006600083602001518152602001908152602001600020600401819055508060a00151600660008360200151815260200190815260200160002060050160008282546117d89190614bc0565b925050819055508060c0015181610120018181516117f69190614bc0565b915081815250508060c001518160a001516118119190614c54565b8160e0018181516118229190614bc0565b915081815250508060c001518160a0015161183d9190614c54565b8460c00181815161184e9190614bc0565b915081815250508060c001518460200181815161186b9190614bc0565b915081815250504260066000836020015181526020019081526020016000206000018190555080602001517f271adf7ca5026da9466c7e2ee50294432b6518106821bb0baa27adfbe5203bad60405160405180910390a260006006600083602001518152602001908152602001600020600201540361199d576007600660008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061192a8160000151826020015161375d565b61193f8c8f8361014001518460200151613852565b6119548c8f8361014001518460200151613b10565b6119638c8f8360200151613bd7565b60016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250506119d1565b60068060008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055505b60008460400151036119f657600784610160019060ff16908160ff1681525050611a0f565b600684610160019060ff16908160ff16815250506112f6565b60008160e001511115611aa95773c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128d8661012001518460e001516040518463ffffffff1660e01b8152600401611a7693929190614bf4565b600060405180830381600087803b158015611a9057600080fd5b505af1158015611aa4573d6000803e3d6000fd5b505050505b60008161010001511115611b3e5773c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663fd9be5228f8361010001516040518363ffffffff1660e01b8152600401611b0b929190614ce8565b600060405180830381600087803b158015611b2557600080fd5b505af1158015611b39573d6000803e3d6000fd5b505050505b60008161012001511115611bd35773c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663fd9be5228d8361012001516040518363ffffffff1660e01b8152600401611ba0929190614ce8565b600060405180830381600087803b158015611bba57600080fd5b505af1158015611bce573d6000803e3d6000fd5b505050505b505b8260066000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101008201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160090160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101408201518160090160146101000a81548160ff021916908360ff1602179055506101608201518160090160156101000a81548160ff021916908360ff160217905550905050600183610160015160ff161480611d6c5750600683610160015160ff16145b15611d9e57611d88611d808e8d60006132b4565b88848b613c8a565b611d998d8c85610120015185613d75565b611dbb565b611daf8d8c85610120015185613b10565b611dba8d8c84613bd7565b5b817f2f539bcf68b0eef24f9fef1ae5ad7dd5a37f80a2fab34f406ad2b92c779d606460405160405180910390a28193505050509a9950505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154925060008303611ead57600167ffffffffffffffff811115611e7757611e76614829565b5b604051908082528060200260200182016040528015611ea55781602001602082028036833780820191505090505b509050612253565b600080600984611ebd9190614a72565b67ffffffffffffffff811115611ed657611ed5614829565b5b604051908082528060200260200182016040528015611f045781602001602082028036833780820191505090505b50905060005b8481101561224c57600086031561224c5785828480611f2890614acc565b955081518110611f3b57611f3a614b14565b5b6020026020010181815250506006600087815260200190815260200160002060000154828480611f6a90614acc565b955081518110611f7d57611f7c614b14565b5b6020026020010181815250506006600087815260200190815260200160002060030154828480611fac90614acc565b955081518110611fbf57611fbe614b14565b5b6020026020010181815250506006600087815260200190815260200160002060020154828480611fee90614acc565b95508151811061200157612000614b14565b5b6020026020010181815250506006600087815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061206690614acc565b95508151811061207957612078614b14565b5b60200260200101818152505060066000878152602001908152602001600020600401548284806120a890614acc565b9550815181106120bb576120ba614b14565b5b6020026020010181815250506006600087815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061212090614acc565b95508151811061213357612132614b14565b5b6020026020010181815250506006600087815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061217290614acc565b95508151811061218557612184614b14565b5b6020026020010181815250506006600087815260200190815260200160002060090160159054906101000a900460ff1660ff168284806121c490614acc565b9550815181106121d7576121d6614b14565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600101549550808061224490614acc565b915050611f0a565b5080925050505b9392505050565b60606000600767ffffffffffffffff81111561227957612278614829565b5b6040519080825280602002602001820160405280156122a75781602001602082028036833780820191505090505b5090506006600084815260200190815260200160002060090160159054906101000a900460ff1660ff16816000815181106122e5576122e4614b14565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff168160018151811061232c5761232b614b14565b5b60200260200101818152505060066000848152602001908152602001600020600201548160028151811061236357612362614b14565b5b60200260200101818152505060066000848152602001908152602001600020600401548160038151811061239a57612399614b14565b5b6020026020010181815250506006600084815260200190815260200160002060050154816004815181106123d1576123d0614b14565b5b60200260200101818152505060066000848152602001908152602001600020600601548160058151811061240857612407614b14565b5b60200260200101818152505060066000848152602001908152602001600020600101548160068151811061243f5761243e614b14565b5b60200260200101818152505080915050919050565b606060008060005b84518110156126545784818151811061247857612477614b14565b5b602002602001015191506006600083815260200190815260200160002060090160159054906101000a900460ff1692503373ffffffffffffffffffffffffffffffffffffffff166006600084815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612538575060048360ff161480612529575060078360ff16145b80612537575060098360ff16145b5b1561261f576125bd6125b76006600085815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633613337565b83613f9a565b60086006600084815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550817fbd000546857b596b03c884060c13e7d8c7a7ce52366d2f116f76688e6f000f6660405160405180910390a2612641565b600085828151811061263457612633614b14565b5b6020026020010181815250505b808061264c90614acc565b91505061245c565b508392505050919050565b6060600061266e878787613337565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036126f457600167ffffffffffffffff8111156126bd576126bc614829565b5b6040519080825280602002602001820160405280156126eb5781602001602082028036833780820191505090505b5091505061292d565b6000806006856127049190614a72565b67ffffffffffffffff81111561271d5761271c614829565b5b60405190808252806020026020018201604052801561274b5781602001602082028036833780820191505090505b50905060005b85811015612925576000870315612925578682848061276f90614acc565b95508151811061278257612781614b14565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff168284806127c190614acc565b9550815181106127d4576127d3614b14565b5b602002602001018181525050600660008881526020019081526020016000206000015482848061280390614acc565b95508151811061281657612815614b14565b5b602002602001018181525050600660008881526020019081526020016000206003015482848061284590614acc565b95508151811061285857612857614b14565b5b602002602001018181525050600660008881526020019081526020016000206005015482848061288790614acc565b95508151811061289a57612899614b14565b5b60200260200101818152505060066000888152602001908152602001600020600601548284806128c990614acc565b9550815181106128dc576128db614b14565b5b602002602001018181525050600460008581526020019081526020016000206000888152602001908152602001600020600101549650808061291d90614acc565b915050612751565b508093505050505b95945050505050565b60606000612946848460016132b4565b90506000600560008381526020019081526020016000206000603381106129705761296f614b14565b5b01549050600081036129cf57600167ffffffffffffffff81111561299757612996614829565b5b6040519080825280602002602001820160405280156129c55781602001602082028036833780820191505090505b5092505050612c41565b600080600061012c67ffffffffffffffff8111156129f0576129ef614829565b5b604051908082528060200260200182016040528015612a1e5781602001602082028036833780820191505090505b50905060005b6032811015612c3757600560008781526020019081526020016000208560338110612a5257612a51614b14565b5b0154925082828580612a6390614acc565b965081518110612a7657612a75614b14565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff16828580612ab590614acc565b965081518110612ac857612ac7614b14565b5b6020026020010181815250506006600084815260200190815260200160002060000154828580612af790614acc565b965081518110612b0a57612b09614b14565b5b6020026020010181815250506006600084815260200190815260200160002060030154828580612b3990614acc565b965081518110612b4c57612b4b614b14565b5b6020026020010181815250506006600084815260200190815260200160002060050154828580612b7b90614acc565b965081518110612b8e57612b8d614b14565b5b6020026020010181815250506006600084815260200190815260200160002060060154828580612bbd90614acc565b965081518110612bd057612bcf614b14565b5b602002602001018181525050600085612be890614c2b565b95508503612c2457603294506000600560008881526020019081526020016000208660338110612c1b57612c1a614b14565b5b01540315612c37575b8080612c2f90614acc565b915050612a24565b5080955050505050505b92915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606000612c7d858560006132b4565b90506000806001600084815260200190815260200160002060008081526020019081526020016000206002015490506000600386612cbb9190614a72565b67ffffffffffffffff811115612cd457612cd3614829565b5b604051908082528060200260200182016040528015612d025781602001602082028036833780820191505090505b50905060005b86811015612e1c576000830315612e1c576006600084815260200190815260200160002060030154828580612d3c90614acc565b965081518110612d4f57612d4e614b14565b5b6020026020010181815250506006600084815260200190815260200160002060020154828580612d7e90614acc565b965081518110612d9157612d90614b14565b5b6020026020010181815250506006600084815260200190815260200160002060040154828580612dc090614acc565b965081518110612dd357612dd2614b14565b5b6020026020010181815250506001600086815260200190815260200160002060008481526020019081526020016000206002015492508080612e1490614acc565b915050612d08565b50809450505050509392505050565b60005481565b60606000806000806000805b875181101561313557878181518110612e5957612e58614b14565b5b602002602001015194506006600086815260200190815260200160002060090160159054906101000a900460ff1695503373ffffffffffffffffffffffffffffffffffffffff166006600087815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612f0b575060018660ff161480612f0a575060068660ff16145b5b1561310057600660008681526020019081526020016000206002015493506006600086815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692506006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128433876040518463ffffffff1660e01b8152600401612fec93929190614bf4565b600060405180830381600087803b15801561300657600080fd5b505af115801561301a573d6000803e3d6000fd5b50505050426006600087815260200190815260200160002060000181905550600060066000878152602001908152602001600020600201819055506000600660008781526020019081526020016000206004018190555060046006600087815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055506130b66130b0848460006132b4565b8661375d565b6130c283833388613852565b6130ce83833388613b10565b847f935c9ad2f1fda9d7eae0d2a512f1521cb7190ee06165414e722366a65975fb6b60405160405180910390a2613122565b600088828151811061311557613114614b14565b5b6020026020010181815250505b808061312d90614acc565b915050612e3d565b508695505050505050919050565b60606000613152878787613337565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036131d857600167ffffffffffffffff8111156131a1576131a0614829565b5b6040519080825280602002602001820160405280156131cf5781602001602082028036833780820191505090505b509150506132ab565b6000808467ffffffffffffffff8111156131f5576131f4614829565b5b6040519080825280602002602001820160405280156132235781602001602082028036833780820191505090505b50905060005b858110156132a35760008703156132a3578682848061324790614acc565b95508151811061325a57613259614b14565b5b602002602001018181525050600460008581526020019081526020016000206000888152602001908152602001600020600101549650808061329b90614acc565b915050613229565b508093505050505b95945050505050565b60008115613302578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16106132f65782846132f9565b83835b80945081955050505b8383604051602001613315929190614d59565b6040516020818303038152906040528051906020012060001c90509392505050565b600080613346858560016132b4565b9050808360405160200161335b929190614da6565b6040516020818303038152906040528051906020012060001c9150509392505050565b6000806000806000600160008a8152602001908152602001600020600089815260200190815260200160002060000154116133e057600160008981526020019081526020016000206000808152602001908152602001600020600201546133e2565b865b9650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600082036134255760006001935093505050613754565b60018560ff16036135c45781861015613512576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b818610156134dd576000810361348157866001935093505050613754565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600101549050613463565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613754565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b8186106135b6576000810361355a57600080935093505050613754565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060020154905061353d565b866000935093505050613754565b818611156136a6576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b81861115613671576000810361361557866001935093505050613754565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206001015490506135f7565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613754565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861161374a57600081036136ee57600080935093505050613754565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206002015490506136d1565b8660009350935050505b94509492505050565b600060016000848152602001908152602001600020600083815260200190815260200160002060010154905060006001600085815260200190815260200160002060008481526020019081526020016000206002015490508160016000868152602001908152602001600020600083815260200190815260200160002060010181905550806001600086815260200190815260200160002060008481526020019081526020016000206002018190555060016000858152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600080820160009055600182016000905550506000613a22878787613337565b9050600360008281526020019081526020016000206000858152602001908152602001600020600001549250600360008281526020019081526020016000206000858152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555081600360008381526020019081526020016000206000858152602001908152602001600020600101819055506003600082815260200190815260200160002060008581526020019081526020016000206000808201600090556001820160009055505050505050505050565b6000613b1d858585613337565b90506000600460008381526020019081526020016000206000808152602001908152602001600020600101549050826004600084815260200190815260200160002060008381526020019081526020016000206000018190555082600460008481526020019081526020016000206000808152602001908152602001600020600101819055508060046000848152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b6000613be5848460016132b4565b9050600060056000838152602001908152602001600020600060338110613c0f57613c0e614b14565b5b0154905060328103613c2057600090505b80613c2a90614acc565b905082600560008481526020019081526020016000208260338110613c5257613c51614b14565b5b01819055508060056000848152602001908152602001600020600060338110613c7e57613c7d614b14565b5b01819055505050505050565b6000600160008681526020019081526020016000206000858152602001908152602001600020600101549050826001600087815260200190815260200160002060008681526020019081526020016000206001018190555082600160008781526020019081526020016000206000838152602001908152602001600020600201819055506040518060600160405280838152602001828152602001858152506001600087815260200190815260200160002060008581526020019081526020016000206000820151816000015560208201518160010155604082015181600201559050505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060010154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206001018190555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101819055506000613ee2868686613337565b9050600360008281526020019081526020016000206000808152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555082600360008381526020019081526020016000206000808152602001908152602001600020600101819055508160036000838152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006004600084815260200190815260200160002060008381526020019081526020016000206000015490506000600460008581526020019081526020016000206000848152602001908152602001600020600101549050816004600086815260200190815260200160002060008381526020019081526020016000206000018190555080600460008681526020019081526020016000206000848152602001908152602001600020600101819055506004600085815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505050505050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6141c7816141b4565b81146141d257600080fd5b50565b6000813590506141e4816141be565b92915050565b600060208284031215614200576141ff6141aa565b5b600061420e848285016141d5565b91505092915050565b614220816141b4565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061425182614226565b9050919050565b61426181614246565b82525050565b600060ff82169050919050565b61427d81614267565b82525050565b6101808201600082015161429a6000850182614217565b5060208201516142ad6020850182614217565b5060408201516142c06040850182614217565b5060608201516142d36060850182614217565b5060808201516142e66080850182614217565b5060a08201516142f960a0850182614217565b5060c082015161430c60c0850182614217565b5060e082015161431f60e0850182614258565b50610100820151614334610100850182614258565b50610120820151614349610120850182614258565b5061014082015161435e610140850182614274565b50610160820151614373610160850182614274565b50505050565b60006101808201905061438f6000830184614283565b92915050565b61439e81614246565b82525050565b60006020820190506143b96000830184614395565b92915050565b6143c881614246565b81146143d357600080fd5b50565b6000813590506143e5816143bf565b92915050565b60008060008060808587031215614405576144046141aa565b5b6000614413878288016143d6565b9450506020614424878288016143d6565b9350506040614435878288016141d5565b9250506060614446878288016141d5565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061448a8383614217565b60208301905092915050565b6000602082019050919050565b60006144ae82614452565b6144b8818561445d565b93506144c38361446e565b8060005b838110156144f45781516144db888261447e565b97506144e683614496565b9250506001810190506144c7565b5085935050505092915050565b6000602082019050818103600083015261451b81846144a3565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261454857614547614523565b5b8235905067ffffffffffffffff81111561456557614564614528565b5b6020830191508360208202830111156145815761458061452d565b5b9250929050565b6000806020838503121561459f5761459e6141aa565b5b600083013567ffffffffffffffff8111156145bd576145bc6141af565b5b6145c985828601614532565b92509250509250929050565b600080600080600060a086880312156145f1576145f06141aa565b5b60006145ff888289016143d6565b9550506020614610888289016143d6565b9450506040614621888289016143d6565b9350506060614632888289016141d5565b9250506080614643888289016141d5565b9150509295509295909350565b60008060408385031215614667576146666141aa565b5b6000614675858286016141d5565b9250506020614686858286016141d5565b9150509250929050565b61469981614267565b81146146a457600080fd5b50565b6000813590506146b681614690565b92915050565b6000806000806000806000806000806101408b8d0312156146e0576146df6141aa565b5b60006146ee8d828e016143d6565b9a505060206146ff8d828e016143d6565b99505060406147108d828e016141d5565b98505060606147218d828e016143d6565b97505060806147328d828e016141d5565b96505060a06147438d828e016146a7565b95505060c06147548d828e016141d5565b94505060e06147658d828e016141d5565b9350506101006147778d828e016141d5565b9250506101206147898d828e016141d5565b9150509295989b9194979a5092959850565b6147a4816141b4565b82525050565b60006020820190506147bf600083018461479b565b92915050565b6000806000606084860312156147de576147dd6141aa565b5b60006147ec868287016143d6565b93505060206147fd868287016141d5565b925050604061480e868287016141d5565b9150509250925092565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61486182614818565b810181811067ffffffffffffffff821117156148805761487f614829565b5b80604052505050565b60006148936141a0565b905061489f8282614858565b919050565b600067ffffffffffffffff8211156148bf576148be614829565b5b602082029050602081019050919050565b60006148e36148de846148a4565b614889565b905080838252602082019050602084028301858111156149065761490561452d565b5b835b8181101561492f578061491b88826141d5565b845260208401935050602081019050614908565b5050509392505050565b600082601f83011261494e5761494d614523565b5b813561495e8482602086016148d0565b91505092915050565b60006020828403121561497d5761497c6141aa565b5b600082013567ffffffffffffffff81111561499b5761499a6141af565b5b6149a784828501614939565b91505092915050565b600080604083850312156149c7576149c66141aa565b5b60006149d5858286016143d6565b92505060206149e6858286016143d6565b9150509250929050565b600080600060608486031215614a0957614a086141aa565b5b6000614a17868287016143d6565b9350506020614a28868287016143d6565b9250506040614a39868287016141d5565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a7d826141b4565b9150614a88836141b4565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614ac157614ac0614a43565b5b828202905092915050565b6000614ad7826141b4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614b0957614b08614a43565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732e00000000000000600082015250565b6000614b8a601983614b43565b9150614b9582614b54565b602082019050919050565b60006020820190508181036000830152614bb981614b7d565b9050919050565b6000614bcb826141b4565b9150614bd6836141b4565b9250828201905080821115614bee57614bed614a43565b5b92915050565b6000606082019050614c096000830186614395565b614c166020830185614395565b614c23604083018461479b565b949350505050565b6000614c36826141b4565b915060008203614c4957614c48614a43565b5b600182039050919050565b6000614c5f826141b4565b9150614c6a836141b4565b9250828203905081811115614c8257614c81614a43565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614cc2826141b4565b9150614ccd836141b4565b925082614cdd57614cdc614c88565b5b828204905092915050565b6000604082019050614cfd6000830185614395565b614d0a602083018461479b565b9392505050565b60008160601b9050919050565b6000614d2982614d11565b9050919050565b6000614d3b82614d1e565b9050919050565b614d53614d4e82614246565b614d30565b82525050565b6000614d658285614d42565b601482019150614d758284614d42565b6014820191508190509392505050565b6000819050919050565b614da0614d9b826141b4565b614d85565b82525050565b6000614db28285614d8f565b602082019150614dc28284614d42565b601482019150819050939250505056fea26469706673582212206350a91992d2b60bffb7b34b8f067127b879f481e72ec3f3a4a0c9fdc5f245cb64736f6c63430008100033
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80636da42a15116100a25780638da5cb5b116100715780638da5cb5b1461032a5780639435298b14610348578063af640d0f14610378578063b55fb57414610396578063e0a31339146103c65761010b565b80636da42a151461026a57806375b024051461029a5780637e9da7a2146102ca578063809741ed146102fa5761010b565b8063334503bf116100de578063334503bf146101aa57806336511013146101da57806347402bea1461020a5780635eb2088e1461023a5761010b565b80630e0578f514610110578063127e11971461014057806318df23881461015e578063299821f61461018e575b600080fd5b61012a600480360381019061012591906141ea565b6103f6565b6040516101379190614379565b60405180910390f35b6101486105a6565b60405161015591906143a4565b60405180910390f35b610178600480360381019061017391906143eb565b6105be565b6040516101859190614501565b60405180910390f35b6101a860048036038101906101a39190614588565b610769565b005b6101c460048036038101906101bf91906145d5565b61096b565b6040516101d19190614501565b60405180910390f35b6101f460048036038101906101ef9190614650565b610c42565b6040516102019190614501565b60405180910390f35b610224600480360381019061021f91906146bc565b611112565b60405161023191906147aa565b60405180910390f35b610254600480360381019061024f91906147c5565b611dfc565b6040516102619190614501565b60405180910390f35b610284600480360381019061027f91906141ea565b61225a565b6040516102919190614501565b60405180910390f35b6102b460048036038101906102af9190614967565b612454565b6040516102c19190614501565b60405180910390f35b6102e460048036038101906102df91906145d5565b61265f565b6040516102f19190614501565b60405180910390f35b610314600480360381019061030f91906149b0565b612936565b6040516103219190614501565b60405180910390f35b610332612c47565b60405161033f91906143a4565b60405180910390f35b610362600480360381019061035d91906149f0565b612c6d565b60405161036f9190614501565b60405180910390f35b610380612e2b565b60405161038d91906147aa565b60405180910390f35b6103b060048036038101906103ab9190614967565b612e31565b6040516103bd9190614501565b60405180910390f35b6103e060048036038101906103db91906145d5565b613143565b6040516103ed9190614501565b60405180910390f35b6103fe614087565b6006600083815260200190815260200160002060405180610180016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016008820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016009820160149054906101000a900460ff1660ff1660ff1681526020016009820160159054906101000a900460ff1660ff1660ff16815250509050919050565b73c36755f64e372870ede6f02360495e0f55c3e0e781565b606060006105ce868660006132b4565b90506000600160008381526020019081526020016000206000868152602001908152602001600020600001541161062c576001600082815260200190815260200160002060008081526020019081526020016000206002015461062e565b835b93506000806002856106409190614a72565b67ffffffffffffffff81111561065957610658614829565b5b6040519080825280602002602001820160405280156106875781602001602082028036833780820191505090505b50905060005b8581101561075a57600087031561075a57868284806106ab90614acc565b9550815181106106be576106bd614b14565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600001548284806106fe90614acc565b95508151811061071157610710614b14565b5b602002602001018181525050600160008581526020019081526020016000206000888152602001908152602001600020600201549650808061075290614acc565b91505061068d565b50809350505050949350505050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f090614ba0565b60405180910390fd5b60005b82829050811015610966576008600660008585858181106108205761081f614b14565b5b90506020020135815260200190815260200160002060090160159054906101000a900460ff1660ff1603610953576006600084848481811061086557610864614b14565b5b9050602002013581526020019081526020016000206000808201600090556001820160009055600282016000905560038201600090556004820160009055600582016000905560068201600090556007820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556008820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556009820160146101000a81549060ff02191690556009820160156101000a81549060ff021916905550505b808061095e90614acc565b9150506107fc565b505050565b6060600061097a878787613337565b905060036000828152602001908152602001600020600085815260200190815260200160002060010154935060008403610a0057600167ffffffffffffffff8111156109c9576109c8614829565b5b6040519080825280602002602001820160405280156109f75781602001602082028036833780820191505090505b50915050610c39565b600080600685610a109190614a72565b67ffffffffffffffff811115610a2957610a28614829565b5b604051908082528060200260200182016040528015610a575781602001602082028036833780820191505090505b50905060005b85811015610c31576000870315610c315786828480610a7b90614acc565b955081518110610a8e57610a8d614b14565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff16828480610acd90614acc565b955081518110610ae057610adf614b14565b5b6020026020010181815250506006600088815260200190815260200160002060000154828480610b0f90614acc565b955081518110610b2257610b21614b14565b5b6020026020010181815250506006600088815260200190815260200160002060030154828480610b5190614acc565b955081518110610b6457610b63614b14565b5b6020026020010181815250506006600088815260200190815260200160002060020154828480610b9390614acc565b955081518110610ba657610ba5614b14565b5b6020026020010181815250506006600088815260200190815260200160002060040154828480610bd590614acc565b955081518110610be857610be7614b14565b5b6020026020010181815250506003600085815260200190815260200160002060008881526020019081526020016000206001015496508080610c2990614acc565b915050610a5d565b508093505050505b95945050505050565b60606000600467ffffffffffffffff811115610c6157610c60614829565b5b604051908082528060200260200182016040528015610c8f5781602001602082028036833780820191505090505b5090506000806000806000600660008a815260200190815260200160002060090160159054906101000a900460ff1690506000600660008a815260200190815260200160002060090160159054906101000a900460ff16905060008260ff161115610d6f57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008c815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168095508197505050610de6565b600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1680955081975050505b60018260ff161480610dfb575060068260ff16145b80610e09575060078260ff16145b80610e17575060098260ff16145b15610f1c57600660008b815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610ed257600660008b81526020019081526020016000206002015485610ea79190614bc0565b9450600660008b81526020019081526020016000206006015483610ecb9190614bc0565b9250610f1b565b600660008b81526020019081526020016000206002015483610ef49190614bc0565b9250600660008b81526020019081526020016000206006015485610f189190614bc0565b94505b5b60018160ff161480610f31575060068160ff16145b80610f3f575060078160ff16145b80610f4d575060098160ff16145b1561105257600660008a815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff160361100857600660008a81526020019081526020016000206002015485610fdd9190614bc0565b9450600660008a815260200190815260200160002060060154836110019190614bc0565b9250611051565b600660008a8152602001908152602001600020600201548361102a9190614bc0565b9250600660008a8152602001908152602001600020600601548561104e9190614bc0565b94505b5b8573ffffffffffffffffffffffffffffffffffffffff168760008151811061107d5761107c614b14565b5b602002602001018181525050848760018151811061109e5761109d614b14565b5b6020026020010181815250508373ffffffffffffffffffffffffffffffffffffffff16876002815181106110d5576110d4614b14565b5b60200260200101818152505082876003815181106110f6576110f5614b14565b5b6020026020010181815250508697505050505050505092915050565b600073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461116057600080fd5b611168614087565b4281600001818152505089816040018181525050878160800181815250508681610140019060ff16908160ff1681525050858160600181815250508a8160e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508881610100019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508b81610120019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181610160019060ff16908160ff1681525050600080815461126f90614acc565b91905081905550600080549050600061129561128d8e8d60006132b4565b888a8c61337e565b80925081985050508015611bd5576112ab614130565b6112b78c8f60006132b4565b81600001818152505060016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250505b600081602001511115611a0f5760016000826000015181526020019081526020016000206000826020015181526020019081526020016000206000015481604001818152505060018a60ff16036113575780604001518911611a0f57611363565b80604001518910611a0f575b6000860361141057600984610160019060ff16908160ff168152505073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128f86610120015187604001516040518463ffffffff1660e01b81526004016113d993929190614bf4565b600060405180830381600087803b1580156113f357600080fd5b505af1158015611407573d6000803e3d6000fd5b50505050611a0f565b8561141a90614c2b565b9550600660008260200151815260200190815260200160002060040154816060018181525050806060015184604001511061145957806060015161145f565b83604001515b81608001818152505083604001518460800151826080015186604001516114869190614c54565b6114909190614a72565b61149a9190614cb7565b84608001818152505060008460800151146114b95780608001516114bf565b83604001515b8160a00181815250508060a00151846040018181516114de9190614c54565b915081815250508060a001518460a0018181516114fb9190614bc0565b9150818152505068056bc75e2d63100000878260a0015161151c9190614a72565b6115269190614cb7565b8160c00181815250508060c0015181610100018181516115469190614bc0565b91508181525050600660008260200151815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681610140019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128f8361014001518460c001518560a0015161160b9190614c54565b6040518463ffffffff1660e01b815260040161162993929190614bf4565b600060405180830381600087803b15801561164357600080fd5b505af1158015611657573d6000803e3d6000fd5b505050508060c001518160a0015161166f9190614c54565b600660008360200151815260200190815260200160002060060160008282546116989190614bc0565b925050819055508060c00151600660008360200151815260200190815260200160002060010160008282546116cd9190614bc0565b92505081905550806060015160066000836020015181526020019081526020016000206002015482608001516117039190614a72565b61170d9190614cb7565b8160a001818152505068056bc75e2d63100000878260a001516117309190614a72565b61173a9190614cb7565b8160c00181815250508060a00151600660008360200151815260200190815260200160002060020160008282546117719190614c54565b925050819055508060800151816060015161178c9190614c54565b6006600083602001518152602001908152602001600020600401819055508060a00151600660008360200151815260200190815260200160002060050160008282546117d89190614bc0565b925050819055508060c0015181610120018181516117f69190614bc0565b915081815250508060c001518160a001516118119190614c54565b8160e0018181516118229190614bc0565b915081815250508060c001518160a0015161183d9190614c54565b8460c00181815161184e9190614bc0565b915081815250508060c001518460200181815161186b9190614bc0565b915081815250504260066000836020015181526020019081526020016000206000018190555080602001517f271adf7ca5026da9466c7e2ee50294432b6518106821bb0baa27adfbe5203bad60405160405180910390a260006006600083602001518152602001908152602001600020600201540361199d576007600660008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff16021790555061192a8160000151826020015161375d565b61193f8c8f8361014001518460200151613852565b6119548c8f8361014001518460200151613b10565b6119638c8f8360200151613bd7565b60016000826000015181526020019081526020016000206000808152602001908152602001600020600201548160200181815250506119d1565b60068060008360200151815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055505b60008460400151036119f657600784610160019060ff16908160ff1681525050611a0f565b600684610160019060ff16908160ff16815250506112f6565b60008160e001511115611aa95773c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128d8661012001518460e001516040518463ffffffff1660e01b8152600401611a7693929190614bf4565b600060405180830381600087803b158015611a9057600080fd5b505af1158015611aa4573d6000803e3d6000fd5b505050505b60008161010001511115611b3e5773c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663fd9be5228f8361010001516040518363ffffffff1660e01b8152600401611b0b929190614ce8565b600060405180830381600087803b158015611b2557600080fd5b505af1158015611b39573d6000803e3d6000fd5b505050505b60008161012001511115611bd35773c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663fd9be5228d8361012001516040518363ffffffff1660e01b8152600401611ba0929190614ce8565b600060405180830381600087803b158015611bba57600080fd5b505af1158015611bce573d6000803e3d6000fd5b505050505b505b8260066000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101008201518160080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160090160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101408201518160090160146101000a81548160ff021916908360ff1602179055506101608201518160090160156101000a81548160ff021916908360ff160217905550905050600183610160015160ff161480611d6c5750600683610160015160ff16145b15611d9e57611d88611d808e8d60006132b4565b88848b613c8a565b611d998d8c85610120015185613d75565b611dbb565b611daf8d8c85610120015185613b10565b611dba8d8c84613bd7565b5b817f2f539bcf68b0eef24f9fef1ae5ad7dd5a37f80a2fab34f406ad2b92c779d606460405160405180910390a28193505050509a9950505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154925060008303611ead57600167ffffffffffffffff811115611e7757611e76614829565b5b604051908082528060200260200182016040528015611ea55781602001602082028036833780820191505090505b509050612253565b600080600984611ebd9190614a72565b67ffffffffffffffff811115611ed657611ed5614829565b5b604051908082528060200260200182016040528015611f045781602001602082028036833780820191505090505b50905060005b8481101561224c57600086031561224c5785828480611f2890614acc565b955081518110611f3b57611f3a614b14565b5b6020026020010181815250506006600087815260200190815260200160002060000154828480611f6a90614acc565b955081518110611f7d57611f7c614b14565b5b6020026020010181815250506006600087815260200190815260200160002060030154828480611fac90614acc565b955081518110611fbf57611fbe614b14565b5b6020026020010181815250506006600087815260200190815260200160002060020154828480611fee90614acc565b95508151811061200157612000614b14565b5b6020026020010181815250506006600087815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061206690614acc565b95508151811061207957612078614b14565b5b60200260200101818152505060066000878152602001908152602001600020600401548284806120a890614acc565b9550815181106120bb576120ba614b14565b5b6020026020010181815250506006600087815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682848061212090614acc565b95508151811061213357612132614b14565b5b6020026020010181815250506006600087815260200190815260200160002060090160149054906101000a900460ff1660ff1682848061217290614acc565b95508151811061218557612184614b14565b5b6020026020010181815250506006600087815260200190815260200160002060090160159054906101000a900460ff1660ff168284806121c490614acc565b9550815181106121d7576121d6614b14565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600101549550808061224490614acc565b915050611f0a565b5080925050505b9392505050565b60606000600767ffffffffffffffff81111561227957612278614829565b5b6040519080825280602002602001820160405280156122a75781602001602082028036833780820191505090505b5090506006600084815260200190815260200160002060090160159054906101000a900460ff1660ff16816000815181106122e5576122e4614b14565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff168160018151811061232c5761232b614b14565b5b60200260200101818152505060066000848152602001908152602001600020600201548160028151811061236357612362614b14565b5b60200260200101818152505060066000848152602001908152602001600020600401548160038151811061239a57612399614b14565b5b6020026020010181815250506006600084815260200190815260200160002060050154816004815181106123d1576123d0614b14565b5b60200260200101818152505060066000848152602001908152602001600020600601548160058151811061240857612407614b14565b5b60200260200101818152505060066000848152602001908152602001600020600101548160068151811061243f5761243e614b14565b5b60200260200101818152505080915050919050565b606060008060005b84518110156126545784818151811061247857612477614b14565b5b602002602001015191506006600083815260200190815260200160002060090160159054906101000a900460ff1692503373ffffffffffffffffffffffffffffffffffffffff166006600084815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612538575060048360ff161480612529575060078360ff16145b80612537575060098360ff16145b5b1561261f576125bd6125b76006600085815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633613337565b83613f9a565b60086006600084815260200190815260200160002060090160156101000a81548160ff021916908360ff160217905550817fbd000546857b596b03c884060c13e7d8c7a7ce52366d2f116f76688e6f000f6660405160405180910390a2612641565b600085828151811061263457612633614b14565b5b6020026020010181815250505b808061264c90614acc565b91505061245c565b508392505050919050565b6060600061266e878787613337565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036126f457600167ffffffffffffffff8111156126bd576126bc614829565b5b6040519080825280602002602001820160405280156126eb5781602001602082028036833780820191505090505b5091505061292d565b6000806006856127049190614a72565b67ffffffffffffffff81111561271d5761271c614829565b5b60405190808252806020026020018201604052801561274b5781602001602082028036833780820191505090505b50905060005b85811015612925576000870315612925578682848061276f90614acc565b95508151811061278257612781614b14565b5b6020026020010181815250506006600088815260200190815260200160002060090160149054906101000a900460ff1660ff168284806127c190614acc565b9550815181106127d4576127d3614b14565b5b602002602001018181525050600660008881526020019081526020016000206000015482848061280390614acc565b95508151811061281657612815614b14565b5b602002602001018181525050600660008881526020019081526020016000206003015482848061284590614acc565b95508151811061285857612857614b14565b5b602002602001018181525050600660008881526020019081526020016000206005015482848061288790614acc565b95508151811061289a57612899614b14565b5b60200260200101818152505060066000888152602001908152602001600020600601548284806128c990614acc565b9550815181106128dc576128db614b14565b5b602002602001018181525050600460008581526020019081526020016000206000888152602001908152602001600020600101549650808061291d90614acc565b915050612751565b508093505050505b95945050505050565b60606000612946848460016132b4565b90506000600560008381526020019081526020016000206000603381106129705761296f614b14565b5b01549050600081036129cf57600167ffffffffffffffff81111561299757612996614829565b5b6040519080825280602002602001820160405280156129c55781602001602082028036833780820191505090505b5092505050612c41565b600080600061012c67ffffffffffffffff8111156129f0576129ef614829565b5b604051908082528060200260200182016040528015612a1e5781602001602082028036833780820191505090505b50905060005b6032811015612c3757600560008781526020019081526020016000208560338110612a5257612a51614b14565b5b0154925082828580612a6390614acc565b965081518110612a7657612a75614b14565b5b6020026020010181815250506006600084815260200190815260200160002060090160149054906101000a900460ff1660ff16828580612ab590614acc565b965081518110612ac857612ac7614b14565b5b6020026020010181815250506006600084815260200190815260200160002060000154828580612af790614acc565b965081518110612b0a57612b09614b14565b5b6020026020010181815250506006600084815260200190815260200160002060030154828580612b3990614acc565b965081518110612b4c57612b4b614b14565b5b6020026020010181815250506006600084815260200190815260200160002060050154828580612b7b90614acc565b965081518110612b8e57612b8d614b14565b5b6020026020010181815250506006600084815260200190815260200160002060060154828580612bbd90614acc565b965081518110612bd057612bcf614b14565b5b602002602001018181525050600085612be890614c2b565b95508503612c2457603294506000600560008881526020019081526020016000208660338110612c1b57612c1a614b14565b5b01540315612c37575b8080612c2f90614acc565b915050612a24565b5080955050505050505b92915050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606000612c7d858560006132b4565b90506000806001600084815260200190815260200160002060008081526020019081526020016000206002015490506000600386612cbb9190614a72565b67ffffffffffffffff811115612cd457612cd3614829565b5b604051908082528060200260200182016040528015612d025781602001602082028036833780820191505090505b50905060005b86811015612e1c576000830315612e1c576006600084815260200190815260200160002060030154828580612d3c90614acc565b965081518110612d4f57612d4e614b14565b5b6020026020010181815250506006600084815260200190815260200160002060020154828580612d7e90614acc565b965081518110612d9157612d90614b14565b5b6020026020010181815250506006600084815260200190815260200160002060040154828580612dc090614acc565b965081518110612dd357612dd2614b14565b5b6020026020010181815250506001600086815260200190815260200160002060008481526020019081526020016000206002015492508080612e1490614acc565b915050612d08565b50809450505050509392505050565b60005481565b60606000806000806000805b875181101561313557878181518110612e5957612e58614b14565b5b602002602001015194506006600086815260200190815260200160002060090160159054906101000a900460ff1695503373ffffffffffffffffffffffffffffffffffffffff166006600087815260200190815260200160002060090160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015612f0b575060018660ff161480612f0a575060068660ff16145b5b1561310057600660008681526020019081526020016000206002015493506006600086815260200190815260200160002060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692506006600086815260200190815260200160002060080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915073c36755f64e372870ede6f02360495e0f55c3e0e773ffffffffffffffffffffffffffffffffffffffff1663d9caed128433876040518463ffffffff1660e01b8152600401612fec93929190614bf4565b600060405180830381600087803b15801561300657600080fd5b505af115801561301a573d6000803e3d6000fd5b50505050426006600087815260200190815260200160002060000181905550600060066000878152602001908152602001600020600201819055506000600660008781526020019081526020016000206004018190555060046006600087815260200190815260200160002060090160156101000a81548160ff021916908360ff1602179055506130b66130b0848460006132b4565b8661375d565b6130c283833388613852565b6130ce83833388613b10565b847f935c9ad2f1fda9d7eae0d2a512f1521cb7190ee06165414e722366a65975fb6b60405160405180910390a2613122565b600088828151811061311557613114614b14565b5b6020026020010181815250505b808061312d90614acc565b915050612e3d565b508695505050505050919050565b60606000613152878787613337565b9050600460008281526020019081526020016000206000858152602001908152602001600020600101549350600084036131d857600167ffffffffffffffff8111156131a1576131a0614829565b5b6040519080825280602002602001820160405280156131cf5781602001602082028036833780820191505090505b509150506132ab565b6000808467ffffffffffffffff8111156131f5576131f4614829565b5b6040519080825280602002602001820160405280156132235781602001602082028036833780820191505090505b50905060005b858110156132a35760008703156132a3578682848061324790614acc565b95508151811061325a57613259614b14565b5b602002602001018181525050600460008581526020019081526020016000206000888152602001908152602001600020600101549650808061329b90614acc565b915050613229565b508093505050505b95945050505050565b60008115613302578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16106132f65782846132f9565b83835b80945081955050505b8383604051602001613315929190614d59565b6040516020818303038152906040528051906020012060001c90509392505050565b600080613346858560016132b4565b9050808360405160200161335b929190614da6565b6040516020818303038152906040528051906020012060001c9150509392505050565b6000806000806000600160008a8152602001908152602001600020600089815260200190815260200160002060000154116133e057600160008981526020019081526020016000206000808152602001908152602001600020600201546133e2565b865b9650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600082036134255760006001935093505050613754565b60018560ff16036135c45781861015613512576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b818610156134dd576000810361348157866001935093505050613754565b809650600160008981526020019081526020016000206000888152602001908152602001600020600001549150600160008981526020019081526020016000206000888152602001908152602001600020600101549050613463565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613754565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b8186106135b6576000810361355a57600080935093505050613754565b80965060016000898152602001908152602001600020600088815260200190815260200160002060000154915060016000898152602001908152602001600020600088815260200190815260200160002060020154905061353d565b866000935093505050613754565b818611156136a6576001600089815260200190815260200160002060008881526020019081526020016000206001015490505b81861115613671576000810361361557866001935093505050613754565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206001015490506135f7565b600160008981526020019081526020016000206000888152602001908152602001600020600201546000935093505050613754565b6001600089815260200190815260200160002060008881526020019081526020016000206002015490505b81861161374a57600081036136ee57600080935093505050613754565b8096506001600089815260200190815260200160002060008881526020019081526020016000206000015491506001600089815260200190815260200160002060008881526020019081526020016000206002015490506136d1565b8660009350935050505b94509492505050565b600060016000848152602001908152602001600020600083815260200190815260200160002060010154905060006001600085815260200190815260200160002060008481526020019081526020016000206002015490508160016000868152602001908152602001600020600083815260200190815260200160002060010181905550806001600086815260200190815260200160002060008481526020019081526020016000206002018190555060016000858152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060010181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600080820160009055600182016000905550506000613a22878787613337565b9050600360008281526020019081526020016000206000858152602001908152602001600020600001549250600360008281526020019081526020016000206000858152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555081600360008381526020019081526020016000206000858152602001908152602001600020600101819055506003600082815260200190815260200160002060008581526020019081526020016000206000808201600090556001820160009055505050505050505050565b6000613b1d858585613337565b90506000600460008381526020019081526020016000206000808152602001908152602001600020600101549050826004600084815260200190815260200160002060008381526020019081526020016000206000018190555082600460008481526020019081526020016000206000808152602001908152602001600020600101819055508060046000848152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b6000613be5848460016132b4565b9050600060056000838152602001908152602001600020600060338110613c0f57613c0e614b14565b5b0154905060328103613c2057600090505b80613c2a90614acc565b905082600560008481526020019081526020016000208260338110613c5257613c51614b14565b5b01819055508060056000848152602001908152602001600020600060338110613c7e57613c7d614b14565b5b01819055505050505050565b6000600160008681526020019081526020016000206000858152602001908152602001600020600101549050826001600087815260200190815260200160002060008681526020019081526020016000206001018190555082600160008781526020019081526020016000206000838152602001908152602001600020600201819055506040518060600160405280838152602001828152602001858152506001600087815260200190815260200160002060008581526020019081526020016000206000820151816000015560208201518160010155604082015181600201559050505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060010154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206001018190555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101819055506000613ee2868686613337565b9050600360008281526020019081526020016000206000808152602001908152602001600020600101549150826003600083815260200190815260200160002060008481526020019081526020016000206000018190555082600360008381526020019081526020016000206000808152602001908152602001600020600101819055508160036000838152602001908152602001600020600085815260200190815260200160002060010181905550505050505050565b60006004600084815260200190815260200160002060008381526020019081526020016000206000015490506000600460008581526020019081526020016000206000848152602001908152602001600020600101549050816004600086815260200190815260200160002060008381526020019081526020016000206000018190555080600460008681526020019081526020016000206000848152602001908152602001600020600101819055506004600085815260200190815260200160002060008481526020019081526020016000206000808201600090556001820160009055505050505050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6141c7816141b4565b81146141d257600080fd5b50565b6000813590506141e4816141be565b92915050565b600060208284031215614200576141ff6141aa565b5b600061420e848285016141d5565b91505092915050565b614220816141b4565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061425182614226565b9050919050565b61426181614246565b82525050565b600060ff82169050919050565b61427d81614267565b82525050565b6101808201600082015161429a6000850182614217565b5060208201516142ad6020850182614217565b5060408201516142c06040850182614217565b5060608201516142d36060850182614217565b5060808201516142e66080850182614217565b5060a08201516142f960a0850182614217565b5060c082015161430c60c0850182614217565b5060e082015161431f60e0850182614258565b50610100820151614334610100850182614258565b50610120820151614349610120850182614258565b5061014082015161435e610140850182614274565b50610160820151614373610160850182614274565b50505050565b60006101808201905061438f6000830184614283565b92915050565b61439e81614246565b82525050565b60006020820190506143b96000830184614395565b92915050565b6143c881614246565b81146143d357600080fd5b50565b6000813590506143e5816143bf565b92915050565b60008060008060808587031215614405576144046141aa565b5b6000614413878288016143d6565b9450506020614424878288016143d6565b9350506040614435878288016141d5565b9250506060614446878288016141d5565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061448a8383614217565b60208301905092915050565b6000602082019050919050565b60006144ae82614452565b6144b8818561445d565b93506144c38361446e565b8060005b838110156144f45781516144db888261447e565b97506144e683614496565b9250506001810190506144c7565b5085935050505092915050565b6000602082019050818103600083015261451b81846144a3565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261454857614547614523565b5b8235905067ffffffffffffffff81111561456557614564614528565b5b6020830191508360208202830111156145815761458061452d565b5b9250929050565b6000806020838503121561459f5761459e6141aa565b5b600083013567ffffffffffffffff8111156145bd576145bc6141af565b5b6145c985828601614532565b92509250509250929050565b600080600080600060a086880312156145f1576145f06141aa565b5b60006145ff888289016143d6565b9550506020614610888289016143d6565b9450506040614621888289016143d6565b9350506060614632888289016141d5565b9250506080614643888289016141d5565b9150509295509295909350565b60008060408385031215614667576146666141aa565b5b6000614675858286016141d5565b9250506020614686858286016141d5565b9150509250929050565b61469981614267565b81146146a457600080fd5b50565b6000813590506146b681614690565b92915050565b6000806000806000806000806000806101408b8d0312156146e0576146df6141aa565b5b60006146ee8d828e016143d6565b9a505060206146ff8d828e016143d6565b99505060406147108d828e016141d5565b98505060606147218d828e016143d6565b97505060806147328d828e016141d5565b96505060a06147438d828e016146a7565b95505060c06147548d828e016141d5565b94505060e06147658d828e016141d5565b9350506101006147778d828e016141d5565b9250506101206147898d828e016141d5565b9150509295989b9194979a5092959850565b6147a4816141b4565b82525050565b60006020820190506147bf600083018461479b565b92915050565b6000806000606084860312156147de576147dd6141aa565b5b60006147ec868287016143d6565b93505060206147fd868287016141d5565b925050604061480e868287016141d5565b9150509250925092565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61486182614818565b810181811067ffffffffffffffff821117156148805761487f614829565b5b80604052505050565b60006148936141a0565b905061489f8282614858565b919050565b600067ffffffffffffffff8211156148bf576148be614829565b5b602082029050602081019050919050565b60006148e36148de846148a4565b614889565b905080838252602082019050602084028301858111156149065761490561452d565b5b835b8181101561492f578061491b88826141d5565b845260208401935050602081019050614908565b5050509392505050565b600082601f83011261494e5761494d614523565b5b813561495e8482602086016148d0565b91505092915050565b60006020828403121561497d5761497c6141aa565b5b600082013567ffffffffffffffff81111561499b5761499a6141af565b5b6149a784828501614939565b91505092915050565b600080604083850312156149c7576149c66141aa565b5b60006149d5858286016143d6565b92505060206149e6858286016143d6565b9150509250929050565b600080600060608486031215614a0957614a086141aa565b5b6000614a17868287016143d6565b9350506020614a28868287016143d6565b9250506040614a39868287016141d5565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a7d826141b4565b9150614a88836141b4565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614ac157614ac0614a43565b5b828202905092915050565b6000614ad7826141b4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614b0957614b08614a43565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732e00000000000000600082015250565b6000614b8a601983614b43565b9150614b9582614b54565b602082019050919050565b60006020820190508181036000830152614bb981614b7d565b9050919050565b6000614bcb826141b4565b9150614bd6836141b4565b9250828201905080821115614bee57614bed614a43565b5b92915050565b6000606082019050614c096000830186614395565b614c166020830185614395565b614c23604083018461479b565b949350505050565b6000614c36826141b4565b915060008203614c4957614c48614a43565b5b600182039050919050565b6000614c5f826141b4565b9150614c6a836141b4565b9250828203905081811115614c8257614c81614a43565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614cc2826141b4565b9150614ccd836141b4565b925082614cdd57614cdc614c88565b5b828204905092915050565b6000604082019050614cfd6000830185614395565b614d0a602083018461479b565b9392505050565b60008160601b9050919050565b6000614d2982614d11565b9050919050565b6000614d3b82614d1e565b9050919050565b614d53614d4e82614246565b614d30565b82525050565b6000614d658285614d42565b601482019150614d758284614d42565b6014820191508190509392505050565b6000819050919050565b614da0614d9b826141b4565b614d85565b82525050565b6000614db28285614d8f565b602082019150614dc28284614d42565b601482019150819050939250505056fea26469706673582212206350a91992d2b60bffb7b34b8f067127b879f481e72ec3f3a4a0c9fdc5f245cb64736f6c63430008100033