Contract Address Details

0x11eCFb02737254583703f29D71929DD95BE574dF

Contract Name
AppealStorage
Creator
0x195582–c8d801 at 0xb93b67–04c873
Balance
0 ROSE
Tokens
Fetching tokens...
Transactions
1 Transactions
Transfers
0 Transfers
Gas Used
772,567
Last Balance Update
1922399
Contract name:
AppealStorage




Optimization enabled
true
Compiler version
v0.8.11+commit.d7f03943




Optimization runs
200
EVM Version
default




Verified at
2022-06-19 09:58:58.459498Z

Constructor Arguments

000000000000000000000000a81c9070cdde315180fcb14b783345f77e0871380000000000000000000000006c76489e86e1f9a1c3f51064b3f4f6435e3ba6bd000000000000000000000000307e9d89bdc72336d70c50e6abc1cae76cbdfc5c

Arg [0] (address) : 0xa81c9070cdde315180fcb14b783345f77e087138
Arg [1] (address) : 0x6c76489e86e1f9a1c3f51064b3f4f6435e3ba6bd
Arg [2] (address) : 0x307e9d89bdc72336d70c50e6abc1cae76cbdfc5c

              

Contract source code

pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(
newOwner != address(0),
"Ownable: new owner is the zero address"
);
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
contract UserStorage is Ownable {
struct User {
address userAddr;
string avatar;
string email;
uint isOnline;
uint userFlag;
uint256 credit;
uint regTime;
TradeStats tradeStats;
MorgageStats morgageStats;
}
struct TradeStats {
uint256 tradeTotal;
uint256 restTotal;
}
struct MorgageStats {
uint256 mortgage;
uint256 freezeMortgage;
uint256 relieveMortgage;
uint256 inviteUserCount;
uint256 inviteUserReward;
uint applyRelieveTime;
uint handleRelieveTime;
}
mapping (address => User) public users;
mapping (address => uint256) public userIndex;
User[] public userList;
event addUser(address _userAddr);
event updateUser(string _avatar, string _email, uint _isOnline);
address _restCAddr;
address _orderCAddr;
address _recordCAddr;
address _appealCAddr;
modifier onlyAuthFromAddr() {
require(_restCAddr != address(0), 'Invalid address call rest');
require(_orderCAddr != address(0), 'Invalid address call order');
require(_recordCAddr != address(0), 'Invalid address call record');
require(_appealCAddr != address(0), 'Invalid address call appeal');
_;
}
function authFromContract(address _fromRest, address _fromOrder, address _fromRecord, address _fromAppeal) external onlyOwner {
_restCAddr = _fromRest;
_orderCAddr = _fromOrder;
_recordCAddr = _fromRecord;
_appealCAddr = _fromAppeal;
}
modifier onlyMemberOf() {
require(users[msg.sender].userAddr != address(0), 'has no permission');
_;
}
function _insert(address _addr) internal {
require(_addr != address(0), "UserStorage: addr null is not allowed");
require(users[_addr].userAddr == address(0), "UserStorage: current User exist");
TradeStats memory tradeStats = TradeStats({tradeTotal:0, restTotal:0});
MorgageStats memory morgageStats = MorgageStats({mortgage:0, freezeMortgage:0, relieveMortgage: 0, inviteUserCount:0, inviteUserReward:0, applyRelieveTime:0, handleRelieveTime:0});
User memory u = User({userAddr:_addr, avatar: '', email:'',
isOnline:1, userFlag:0, credit:0, regTime:block.timestamp,tradeStats:tradeStats, morgageStats:morgageStats});
users[_addr] = u;
userList.push(u);
userIndex[_addr] = userList.length -1;
emit addUser(_addr);
}
function _updateInfo(address _addr, string memory _avatar, string memory _email, uint _isOnline) internal {
require(_addr != address(0), "UserStorage: _addr null is not allowed");
require(users[_addr].userAddr != address(0), "UserStorage: current User not exist");
User memory u = users[_addr];
if(bytes(_avatar).length != 0){
u.avatar = _avatar;
}
if(bytes(_email).length != 0){
u.email = _email;
}
if(_isOnline != uint(0)){
u.isOnline = _isOnline;
}
users[_addr] = u;
userList[userIndex[_addr]] = u;
}
function _updateTradeStats(address _addr, TradeStats memory _tradeStats, uint _credit) internal {
require(_addr != address(0), "UserStorage: _addr null is not allowed");
require(users[_addr].userAddr != address(0), "UserStorage: current User not exist");
User memory u = users[_addr];
u.credit = _credit;
u.tradeStats.tradeTotal = _tradeStats.tradeTotal;
u.tradeStats.restTotal = _tradeStats.restTotal;
users[_addr] = u;
userList[userIndex[_addr]] = u;
}
function _updateMorgageStats(address _addr, MorgageStats memory _morgageStats) internal {
require(_addr != address(0), "UserStorage: _addr null is not allowed");
require(users[_addr].userAddr != address(0), "UserStorage: current User not exist");
User memory u = users[_addr];
u.morgageStats.mortgage = _morgageStats.mortgage;
u.morgageStats.freezeMortgage = _morgageStats.freezeMortgage;
u.morgageStats.relieveMortgage = _morgageStats.relieveMortgage;
u.morgageStats.inviteUserCount = _morgageStats.inviteUserCount;
u.morgageStats.inviteUserReward = _morgageStats.inviteUserReward;
u.morgageStats.applyRelieveTime = _morgageStats.applyRelieveTime;
u.morgageStats.handleRelieveTime = _morgageStats.handleRelieveTime;
users[_addr] = u;
userList[userIndex[_addr]] = u;
}
function _search(address _addr) internal view returns(User memory user) {
require(_addr != address(0), "UserStorage: _addr null is not allowed");
require(users[_addr].userAddr != address(0), "UserStorage: current User not exist");
User memory a = users[_addr];
return a;
}
function register() external {
require(!isMemberOf(), 'has registed');
_insert(msg.sender);
}
function isMemberOf() public view returns (bool) {
return (users[msg.sender].userAddr != address(0));
}
function updateInfo(string memory _avatar, string memory _email, uint _isOnline) onlyMemberOf external {
_updateInfo(msg.sender, _avatar, _email, _isOnline);
emit updateUser(_avatar, _email, _isOnline);
}
function updateTradeStats(address _addr, TradeStats memory _tradeStats, uint _credit) onlyAuthFromAddr public {
require(msg.sender == _restCAddr || msg.sender == _orderCAddr || msg.sender == _appealCAddr || msg.sender == _recordCAddr, 'UserStorage:Invalid from contract address');
_updateTradeStats(_addr, _tradeStats, _credit);
}
function updateMorgageStats(address _addr, MorgageStats memory _morgageStats) onlyAuthFromAddr public {
require(msg.sender == _recordCAddr, 'UserStorage:Invalid from contract address');
_updateMorgageStats(_addr, _morgageStats);
}
function updateUserRole(address _addr, uint _userFlag) onlyAuthFromAddr public {
require(msg.sender == _recordCAddr, 'UserStorage:Invalid from contract address');
require(_addr != address(0), "UserStorage: _addr null is not allowed");
require(users[_addr].userAddr != address(0), "UserStorage: current User not exist");
require(_userFlag<=3, 'UserStorage: Invalid userFlag 3');
User memory u = users[_addr];
u.userFlag = _userFlag;
users[_addr] = u;
userList[userIndex[_addr]] = u;
}
function searchUser(address _addr) external view returns(User memory user) {
return _search(_addr);
}
function searchUserList() external view returns(User[] memory) {
return userList;
}
}
abstract contract ReentrancyGuardRest {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
library CountersRest {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
{
if (counter._value == 0) {
counter._value = 10000;
}
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
{
counter._value = value - 1;
}
}
}
contract RestStorage is Ownable,ReentrancyGuardRest {
using CountersRest for CountersRest.Counter;
RecordInterface private _recordStorage;
UserInterface private _userStorage;
address recordAddress;
struct Rest {
address userAddr;
uint restNo;
uint restType;
string coinType;
string currencyType;
uint restCount;
uint price;
uint[] payType;
uint restStatus;
RestDetail restDetail;
}
struct RestDetail {
uint finishCount;
uint remainderCount;
uint limitAmountFrom;
uint limitAmountTo;
uint limitMinCredit;
uint limitMinMortgage;
string restRemark;
uint restTime;
uint updateTime;
uint restFee;
string restHash;
}
CountersRest.Counter private _restNoCounter;
mapping (uint => Rest) private rests;
mapping (uint => uint) private restIndex;
Rest[] private restList;
mapping(address=>mapping(uint=>uint)) restFrozenTotal;
event RestAdd(uint _restNo, uint _restType, string _coinType, string _currencyType, uint _restCount, uint _price, uint[] _payType,RestDetail _restDetail);
event RestUpdate(uint _restNo, string _coinType, string _currencyType, uint _restCount, uint _price,uint[] _payType, RestDetail _restDetail);
address _orderCAddr;
modifier onlyAuthFromAddr() {
require(_orderCAddr == msg.sender, 'Invalid contract address');
_;
}
function authFromContract(address _recordAddr, address _userAddr, address _orderAddr) external onlyOwner {
_orderCAddr = _orderAddr;
_recordStorage = RecordInterface(_recordAddr);
_userStorage = UserInterface(_userAddr);
recordAddress = _recordAddr;
_restNoCounter.increment();
}
modifier onlyRestOwner(uint _restNo) {
require(rests[_restNo].userAddr == msg.sender, "rest address not exist");
_;
}
function _checkParam(uint _restType, string memory _coinType, string memory _currencyType,
uint _restCount, uint _price, uint[] memory _payType) pure internal {
require(_restType != uint(0), "RestStorage: restType null is not allowed");
require(bytes(_coinType).length != 0, "RestStorage: coinType null is not allowed");
require(bytes(_currencyType).length != 0, "RestStorage: currencyType null is not allowed");
require(_restCount != uint(0), "RestStorage: restCount null is not allowed");
require(_price != uint(0), "RestStorage: price null is not allowed");
require(_payType.length != 0, "RestStorage: payType null is not allowed");
}
function _insert(uint _restType, string memory _coinType, string memory _currencyType,
uint _restCount, uint _price, uint[] memory _payType, RestDetail memory _restDetail) internal nonReentrant returns(uint){
_checkParam(_restType, _coinType, _currencyType, _restCount, _price, _payType);
uint _restNo = _restNoCounter.current();
require(rests[_restNo].restNo == uint(0), "rest exist");
_restDetail.finishCount = 0;
_restDetail.remainderCount = _restCount;
_restDetail.restTime = block.timestamp;
_restDetail.updateTime = 0;
if(_restDetail.limitAmountTo > SafeMath.mul(_restCount, _price) || _restDetail.limitAmountTo == 0) {
_restDetail.limitAmountTo = SafeMath.mul(_restCount, _price);
}
Rest memory r = Rest({userAddr: msg.sender, restNo: _restNo, restType:_restType,
coinType:_coinType, currencyType:_currencyType,
restCount:_restCount, price:_price,
payType:_payType, restStatus:1, restDetail: _restDetail});
rests[_restNo] = r;
restList.push(r);
restIndex[_restNo] = restList.length-1;
_restNoCounter.increment();
emit RestAdd(_restNo, _restType, _coinType, _currencyType, _restCount, _price, _payType, _restDetail);
return _restNo;
}
function _updateInfo(uint _restNo, string memory _coinType, string memory _currencyType,
uint _addCount, uint _price, uint[] memory _payType, RestDetail memory _restDetail) internal {
require(_restNo != uint(0), 'Invalid restNo');
Rest memory r = rests[_restNo];
r.restStatus = 1;
if(bytes(_coinType).length != 0){
r.coinType = _coinType;
}
if(bytes(_currencyType).length != 0){
r.currencyType = _currencyType;
}
if(_price != uint(0)){
r.price = _price;
}
if(_addCount != uint(0)){
r.restCount += _addCount;
r.restDetail.remainderCount += _addCount;
r.restDetail.limitAmountTo = SafeMath.mul(r.restDetail.remainderCount, r.price);
}
if(_payType.length != 0){
r.payType = _payType;
}
if(_restDetail.limitAmountFrom != uint(0)){
if(_restDetail.limitAmountFrom > r.restDetail.limitAmountTo) {
_restDetail.limitAmountFrom = r.restDetail.limitAmountTo;
}
r.restDetail.limitAmountFrom = _restDetail.limitAmountFrom;
}
if(_restDetail.limitMinCredit != uint(0)){
r.restDetail.limitMinCredit = _restDetail.limitMinCredit;
}
if(_restDetail.limitMinMortgage != uint(0)){
r.restDetail.limitMinMortgage = _restDetail.limitMinMortgage;
}
if(bytes(_restDetail.restRemark).length != 0){
r.restDetail.restRemark = _restDetail.restRemark;
}
if(_restDetail.restFee != uint(0)){
r.restDetail.restFee = _restDetail.restFee;
}
r.restDetail.updateTime = block.timestamp;
rests[_restNo] = r;
restList[restIndex[_restNo]] = r;
emit RestUpdate(_restNo, _coinType, _currencyType, r.restCount, _price, _payType, _restDetail);
}
function addBuyRest(uint _restType, string memory _coinType, string memory _currencyType,
uint _restCount, uint _price, uint[] memory _payType,RestDetail memory _restDetail) external {
require(_restType == 1, "must buy rest" );
UserStorage.User memory _user = _userStorage.searchUser(msg.sender);
bool _openTrade = _recordStorage.getOpenTrade();
require(_openTrade || _user.userFlag == 3, "invalid user" );
_insert(_restType, _coinType, _currencyType, _restCount, _price, _payType, _restDetail);
}
function _addSell(uint _restType, string memory _coinType, string memory _currencyType,
uint _restCount, uint _restFee, uint _price, uint[] memory _payType,RestDetail memory _restDetail) internal {
require(_restType == 2, "must sell rest" );
require(_restCount > 0, "restCount error");
UserStorage.User memory _user = _userStorage.searchUser(msg.sender);
bool _openTrade = _recordStorage.getOpenTrade();
require(_openTrade || _user.userFlag == 3, "invalid user" );
_recordStorage.addRecord(msg.sender, '', _coinType, _restCount, 2, 1, 2);
uint _needSub = SafeMath.add(_restCount, _restFee);
TokenTransfer _tokenTransfer = _recordStorage.getERC20Address(_coinType);
_tokenTransfer.transferFrom(msg.sender, recordAddress, _needSub);
uint _newRestNo = _insert(_restType, _coinType, _currencyType, _restCount, _price, _payType, _restDetail);
restFrozenTotal[msg.sender][_newRestNo] = _restCount;
}
function addSellRest(uint _restType, string memory _coinType, string memory _currencyType,
uint _restCount,uint _restFee, uint _price, uint[] memory _payType,RestDetail memory _restDetail) external {
_addSell(_restType, _coinType, _currencyType, _restCount,_restFee,_price, _payType, _restDetail);
}
function getRestFrozenTotal(address _addr, uint _restNo) public view returns(uint) {
return restFrozenTotal[_addr][_restNo];
}
function cancelBuyRest(uint _restNo) external onlyRestOwner(_restNo) {
require(rests[_restNo].restStatus == 1, "can't change this rest");
require(rests[_restNo].restType == 1, "Invalid rest type");
require(rests[_restNo].restDetail.finishCount < rests[_restNo].restCount, "this rest has finished");
Rest memory r = rests[_restNo];
r.restStatus = 4;
r.restDetail.updateTime = block.timestamp;
rests[_restNo] = r;
restList[restIndex[_restNo]] = r;
}
function _cancelSell(uint _restNo) onlyRestOwner(_restNo) internal {
require(rests[_restNo].restStatus == 1, "can't cancel this rest");
require(rests[_restNo].restType == 2, "Invalid rest type");
require(rests[_restNo].restDetail.finishCount < rests[_restNo].restCount, "this rest has finished");
require(restFrozenTotal[msg.sender][_restNo] > 0, "rest has finished");
uint _frozenTotal = _recordStorage.getFrozenTotal(msg.sender, rests[_restNo].coinType);
require(_frozenTotal >= restFrozenTotal[msg.sender][_restNo], "can't cancel this rest");
uint remainHoldCoin = restFrozenTotal[msg.sender][_restNo];
Rest memory r = rests[_restNo];
r.restStatus = 4;
if (remainHoldCoin < rests[_restNo].restCount) {
r.restStatus = 5;
}
r.restDetail.remainderCount = 0;
r.restDetail.updateTime = block.timestamp;
rests[_restNo] = r;
restList[restIndex[_restNo]] = r;
restFrozenTotal[msg.sender][_restNo] = 0;
_recordStorage.addAvailableTotal(msg.sender, rests[_restNo].coinType, remainHoldCoin);
}
function cancelSellRest(uint _restNo) external{
_cancelSell(_restNo);
}
function startOrStop(uint _restNo, uint _restStatus) external onlyRestOwner(_restNo){
require(_restStatus == 1 || _restStatus == 3, "Invalid rest status");
Rest memory r = rests[_restNo];
require(r.restStatus == 1 || r.restStatus == 3, "Invalid rest status,opt error");
r.restStatus = _restStatus;
r.restDetail.updateTime = block.timestamp;
rests[_restNo] = r;
restList[restIndex[_restNo]] = r;
}
function updateInfo(uint _restNo, string memory _coinType, string memory _currencyType,
uint _addCount, uint _restFee, uint _price,uint[] memory _payType, RestDetail memory _restDetail) external onlyRestOwner(_restNo){
require(_restNo != uint(0), 'Invalid restNo');
Rest memory _rest = rests[_restNo];
require(_rest.restNo != uint(0), 'rest not exist');
if (_rest.restType == 2) {
_recordStorage.addRecord(msg.sender, '', _coinType, _addCount, 2, 1, 2);
uint _needSub = SafeMath.add(_addCount, _restFee);
TokenTransfer _tokenTransfer = _recordStorage.getERC20Address(_coinType);
_tokenTransfer.transferFrom(msg.sender, recordAddress, _needSub);
restFrozenTotal[msg.sender][_restNo] += _addCount;
}
_updateInfo(_restNo, _coinType, _currencyType, _addCount, _price, _payType, _restDetail);
}
function updateRestFinishCount(uint _restNo, uint _finishCount) onlyAuthFromAddr external {
Rest memory _rest = rests[_restNo];
require(_rest.restDetail.remainderCount >= _finishCount, "RestStorage:finish count error");
if (_rest.restType == 2) {
restFrozenTotal[_rest.userAddr][_restNo] = SafeMath.sub(restFrozenTotal[_rest.userAddr][_restNo], _finishCount);
}
_rest.restDetail.finishCount = SafeMath.add(_rest.restDetail.finishCount, _finishCount);
_rest.restDetail.remainderCount = SafeMath.sub(_rest.restDetail.remainderCount, _finishCount);
_rest.restDetail.limitAmountTo = SafeMath.mul(_rest.price, _rest.restDetail.remainderCount);
if (_rest.restDetail.remainderCount == 0) {
_rest.restStatus = 2;
}
_rest.restDetail.updateTime = block.timestamp;
rests[_restNo] = _rest;
restList[restIndex[_restNo]] = _rest;
}
function addRestRemainCount(uint _restNo, uint _remainCount) onlyAuthFromAddr public {
Rest memory _rest = rests[_restNo];
require(_remainCount > 0 && _rest.restDetail.finishCount >= _remainCount, "count error");
if (_rest.restType == 2) {
restFrozenTotal[_rest.userAddr][_restNo] = SafeMath.add(restFrozenTotal[_rest.userAddr][_restNo], _remainCount);
}
_rest.restDetail.finishCount = SafeMath.sub(_rest.restDetail.finishCount, _remainCount);
_rest.restDetail.remainderCount = SafeMath.add(_rest.restDetail.remainderCount, _remainCount);
_rest.restDetail.limitAmountTo = SafeMath.mul(_rest.price, _rest.restDetail.remainderCount);
_rest.restDetail.limitAmountFrom = _rest.restDetail.limitAmountFrom > _rest.restDetail.limitAmountTo ? _rest.restDetail.limitAmountTo : _rest.restDetail.limitAmountFrom;
_rest.restStatus = 1;
_rest.restDetail.updateTime = block.timestamp;
rests[_restNo] = _rest;
restList[restIndex[_restNo]] = _rest;
}
function searchRest(uint _restNo) external view returns(Rest memory rest) {
require(_restNo != uint(0), "restNo null is not allowed");
Rest memory r = rests[_restNo];
return r;
}
function searchRestList() external view returns(Rest[] memory) {
return restList;
}
}
abstract contract ReentrancyGuardOrder {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
library CountersOrder {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
{
if (counter._value == 0) {
counter._value = 10000;
}
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
{
counter._value = value - 1;
}
}
}
contract OrderStorage is Ownable, ReentrancyGuardOrder {
using CountersOrder for CountersOrder.Counter;
RestStorage private _restStorage;
RecordInterface private _recordStorage;
UserInterface private _userStorage;
AppealInterface private _appealS;
address recordAddress;
struct Order {
address userAddr;
uint256 orderNo;
uint256 restNo;
uint256 coinCount;
uint256 orderAmount;
uint256 payType;
string currencyType;
uint256 orderType;
uint256 orderStatus;
OrderDetail orderDetail;
}
struct OrderDetail {
address buyerAddr;
address sellerAddr;
string coinType;
uint256 price;
uint256 tradeTime;
uint256 updateTime;
string tradeHash;
uint256 tradeFee;
}
CountersOrder.Counter private _orderNoCounter;
mapping(uint256 => Order) private orders;
mapping(uint256 => uint256) private orderIndex;
Order[] private orderList;
mapping(address => mapping(uint256 => uint256)) orderFrozenTotal;
uint256 cancelOrderTime = 30;
function setCancelOrderTime(uint256 _count) public onlyOwner {
cancelOrderTime = _count;
}
function getCancelOrderTime() public view returns (uint256) {
return cancelOrderTime;
}
uint256 canWithdrawHours = 24;
function setCanWithdrawHours(uint256 _count) public onlyOwner {
canWithdrawHours = _count;
}
function getCanWithdrawHours() public view returns (uint256) {
return canWithdrawHours;
}
event OrderAdd(
uint256 _orderNo,
uint256 _restNo,
uint256 _coinCount,
uint256 _tradeFee,
uint256 _orderAmount,
uint256 _payType,
uint256 _orderType,
address _buyerAddr,
address _sellerAddr
);
event OrderPaidMoney(uint256 _orderNo);
event OrderConfirmCollect(uint256 _orderNo);
event OrderCancel(uint256 _orderNo);
event OrderUpdateStatus(uint256 _orderNo, uint256 _orderStatus);
function authFromContract(
address _recordAddr,
address _restAddr,
address _userAddr,
address _appealAddr
) external onlyOwner {
_recordStorage = RecordInterface(_recordAddr);
_restStorage = RestStorage(_restAddr);
_userStorage = UserInterface(_userAddr);
recordAddress = _recordAddr;
_appealS = AppealInterface(_appealAddr);
_orderNoCounter.increment();
}
modifier onlyBuyer(uint256 _orderNo) {
require(_orderNo != uint256(0), "orderNo null");
require(
orders[_orderNo].orderDetail.buyerAddr == msg.sender,
"only buyer"
);
_;
}
modifier onlySeller(uint256 _orderNo) {
require(_orderNo != uint256(0), "orderNo null");
require(
orders[_orderNo].orderDetail.sellerAddr == msg.sender,
"only seller"
);
_;
}
modifier onlyBuyerOrSeller(uint256 _orderNo) {
require(_orderNo != uint256(0), "orderNo null");
require(
orders[_orderNo].orderDetail.sellerAddr == msg.sender ||
orders[_orderNo].orderDetail.buyerAddr == msg.sender,
"Only buyer or seller"
);
_;
}
function _checkParam(
uint256 _restNo,
uint256 _coinCount,
uint256 _orderAmount,
uint256 _payType
) internal pure {
require(_restNo != uint256(0), "restNo null");
require(_coinCount > 0, "coinCount null");
require(_orderAmount > 0, "orderAmount null");
require(_payType != uint256(0), "payType null");
}
function _insert(
uint256 _restNo,
uint256 _coinCount,
uint256 _tradeFee,
uint256 _orderAmount,
uint256 _payType,
uint256 _orderType,
address _buyerAddr,
address _sellerAddr
) internal nonReentrant returns (uint256 restNo) {
_checkParam(_restNo, _coinCount, _orderAmount, _payType);
RestStorage.Rest memory _rest = _restStorage.searchRest(_restNo);
require(_rest.userAddr != address(0), "rest not exist");
OrderDetail memory _orderDetail = OrderDetail({
buyerAddr: _buyerAddr,
sellerAddr: _sellerAddr,
coinType: _rest.coinType,
price: _rest.price,
tradeTime: block.timestamp,
updateTime: 0,
tradeHash: "",
tradeFee: _tradeFee
});
uint256 _orderNo = _orderNoCounter.current();
require(orders[_orderNo].orderNo == uint256(0), "order exist");
Order memory order = Order({
userAddr: msg.sender,
orderNo: _orderNo,
restNo: _restNo,
coinCount: _coinCount,
orderAmount: _orderAmount,
payType: _payType,
currencyType: _rest.currencyType,
orderType: _orderType,
orderStatus: 1,
orderDetail: _orderDetail
});
orders[_orderNo] = order;
orderList.push(order);
orderIndex[_orderNo] = orderList.length - 1;
if (_orderType == 2) {
orderFrozenTotal[msg.sender][_orderNo] = _coinCount;
} else if (_orderType == 1) {
orderFrozenTotal[_rest.userAddr][_orderNo] = _coinCount;
}
_orderNoCounter.increment();
emit OrderAdd(
_orderNo,
_restNo,
_coinCount,
_tradeFee,
_orderAmount,
_payType,
_orderType,
_buyerAddr,
_sellerAddr
);
return _orderNo;
}
function addBuyOrder(
uint256 _restNo,
uint256 _coinCount,
uint256 _orderAmount,
uint256 _payType
) external {
RestStorage.Rest memory _rest = _restStorage.searchRest(_restNo);
require(_rest.userAddr != msg.sender, "rest not exist");
require(_rest.restType == 2, "sell rest not exist");
require(_coinCount > 0 && _orderAmount > 0, "coin count error");
require(_rest.restStatus == 1, "rest status error");
UserStorage.User memory _currentUser = _userStorage.searchUser(
msg.sender
);
require(
_currentUser.userFlag != 1 && _currentUser.userFlag != 2,
"invalid user"
);
uint256 _restFrozen = _restStorage.getRestFrozenTotal(
_rest.userAddr,
_restNo
);
require(_restFrozen >= _coinCount, "coin not enough");
uint256 _amo = SafeMath.mul(_rest.price, _coinCount);
require(
_amo >= _rest.restDetail.limitAmountFrom &&
_amo <= _rest.restDetail.limitAmountTo,
"amount error"
);
require(
_currentUser.credit >= _rest.restDetail.limitMinCredit,
"credit error"
);
require(
_currentUser.morgageStats.mortgage >=
_rest.restDetail.limitMinMortgage,
"mortgage error"
);
_restStorage.updateRestFinishCount(_restNo, _coinCount);
_insert(
_restNo,
_coinCount,
0,
_orderAmount,
_payType,
1,
msg.sender,
_rest.userAddr
);
}
function addSellOrder(
uint256 _restNo,
uint256 _coinCount,
uint256 _tradeFee,
uint256 _orderAmount,
uint256 _payType
) external {
RestStorage.Rest memory _rest = _restStorage.searchRest(_restNo);
require(_rest.userAddr != msg.sender, "rest not exist");
require(_rest.restType == 1, "buy rest not exist");
require(_coinCount > 0, "coin count error");
require(_orderAmount > 0, "orderAmount error");
require(_rest.restStatus == 1, "rest status error");
uint256 _amo = SafeMath.mul(_rest.price, _coinCount);
require(
_amo >= _rest.restDetail.limitAmountFrom &&
_amo <= _rest.restDetail.limitAmountTo,
"amount error"
);
UserStorage.User memory _currentUser = _userStorage.searchUser(
msg.sender
);
require(
_currentUser.userFlag != 1 && _currentUser.userFlag != 2,
"invalid user"
);
require(
_currentUser.credit >= _rest.restDetail.limitMinCredit,
"credit error"
);
require(
_currentUser.morgageStats.mortgage >=
_rest.restDetail.limitMinMortgage,
"mortgage error"
);
uint256 _needSub = SafeMath.add(_coinCount, _tradeFee);
_restStorage.updateRestFinishCount(_restNo, _coinCount);
_insert(
_restNo,
_coinCount,
_tradeFee,
_orderAmount,
_payType,
2,
_rest.userAddr,
msg.sender
);
TokenTransfer _tokenTransfer = _recordStorage.getERC20Address(
_rest.coinType
);
_tokenTransfer.transferFrom(msg.sender, recordAddress, _needSub);
_recordStorage.addRecord(
msg.sender,
"",
_rest.coinType,
_coinCount,
2,
1,
2
);
}
function setPaidMoney(uint256 _orderNo)
external
onlyBuyer(_orderNo)
returns (bool)
{
_updateOrderStatus(_orderNo, 2);
emit OrderPaidMoney(_orderNo);
return true;
}
function confirmCollect(uint256 _orderNo) external onlySeller(_orderNo) {
require(_orderNo != uint256(0), "orderNo null");
Order memory _order = orders[_orderNo];
require(_order.orderStatus == 2, "Invalid order status");
require(
_order.orderDetail.buyerAddr != address(0),
"Invalid buyer address"
);
require(
orderFrozenTotal[msg.sender][_orderNo] >= _order.coinCount,
"coin not enough"
);
_updateOrderStatus(_orderNo, 3);
orderFrozenTotal[msg.sender][_orderNo] = 0;
uint256 _rc = _recordStorage.getTradeCredit();
UserStorage.User memory _user = _userStorage.searchUser(msg.sender);
uint256 _credit = _user.credit + _rc;
UserStorage.TradeStats memory _tradeStats = _user.tradeStats;
_tradeStats.tradeTotal += 1;
_userStorage.updateTradeStats(msg.sender, _tradeStats, _credit);
UserStorage.User memory _user2 = _userStorage.searchUser(
_order.orderDetail.buyerAddr
);
uint256 _credit2 = _user2.credit + _rc;
UserStorage.TradeStats memory _tradeStats2 = _user2.tradeStats;
_tradeStats2.tradeTotal += 1;
_userStorage.updateTradeStats(
_order.orderDetail.buyerAddr,
_tradeStats2,
_credit2
);
_recordStorage.subFrozenTotal(_orderNo, _order.orderDetail.buyerAddr);
emit OrderConfirmCollect(_orderNo);
}
function cancelOrder(uint256 _orderNo)
external
onlyBuyerOrSeller(_orderNo)
returns (bool)
{
Order memory _order = orders[_orderNo];
require(_order.orderNo != uint256(0), "current Order not exist");
require(_order.orderStatus == 1, "Can't cancel order");
if (_order.orderDetail.sellerAddr == msg.sender) {
require(
_order.orderDetail.tradeTime + cancelOrderTime * 1 minutes <
block.timestamp,
"limit"
);
}
RestStorage.Rest memory _rest = _restStorage.searchRest(_order.restNo);
if (_rest.restStatus == 4 || _rest.restStatus == 5) {
orderFrozenTotal[_order.orderDetail.sellerAddr][_orderNo] = 0;
_recordStorage.addAvailableTotal(
_order.orderDetail.sellerAddr,
_order.orderDetail.coinType,
_order.coinCount
);
} else {
if (_order.orderType == 2) {
orderFrozenTotal[_order.orderDetail.sellerAddr][_orderNo] = 0;
_recordStorage.addAvailableTotal(
_order.orderDetail.sellerAddr,
_order.orderDetail.coinType,
_order.coinCount
);
}
_restStorage.addRestRemainCount(_order.restNo, _order.coinCount);
}
_updateOrderStatus(_orderNo, 4);
emit OrderCancel(_orderNo);
return true;
}
function takeCoin(uint256 _o) external onlyBuyerOrSeller(_o) {
AppealStorage.Appeal memory _appeal = _appealS.searchAppeal(_o);
require(
block.timestamp - _appeal.detail.witnessHandleTime >
canWithdrawHours * 1 hours,
"time error"
);
address _win;
if (_appeal.user == _appeal.buyer) {
if (_appeal.status == 2) {
_win = _appeal.buyer;
} else if (_appeal.status == 3) {
_win = _appeal.seller;
}
} else {
if (_appeal.status == 2) {
_win = _appeal.seller;
} else if (_appeal.status == 3) {
_win = _appeal.buyer;
}
}
require(_win == msg.sender, "opt error");
_updateOrderStatus(_o, 5);
orderFrozenTotal[_appeal.seller][_o] = 0;
_recordStorage.subFrozenTotal(_o, msg.sender);
}
function _updateOrderStatus(uint256 _orderNo, uint256 _orderStatus)
internal
onlyBuyerOrSeller(_orderNo)
{
Order memory order = orders[_orderNo];
require(order.orderNo != uint256(0), "current Order not exist");
require(_orderStatus >= 1 && _orderStatus <= 5, "Invalid order status");
if (_orderStatus == 2 && order.orderStatus != 1) {
revert("Invalid order status 2");
}
if (_orderStatus == 3 && order.orderStatus != 2) {
revert("Invalid order status 3");
}
if (_orderStatus == 4 && order.orderStatus != 1) {
revert("Invalid order status 4");
}
if (
_orderStatus == 5 &&
order.orderStatus != 1 &&
order.orderStatus != 2
) {
revert("Invalid order status 5");
}
if (_orderStatus == 2) {
require(
order.orderDetail.buyerAddr == msg.sender,
"only buyer call"
);
}
if (_orderStatus == 3) {
require(
order.orderDetail.sellerAddr == msg.sender,
"only seller call"
);
}
order.orderStatus = _orderStatus;
order.orderDetail.updateTime = block.timestamp;
orders[_orderNo] = order;
orderList[orderIndex[_orderNo]] = order;
emit OrderUpdateStatus(_orderNo, _orderStatus);
}
function searchOrder(uint256 _orderNo)
external
view
returns (Order memory order)
{
require(_orderNo != uint256(0), "orderNo null");
require(
orders[_orderNo].orderNo != uint256(0),
"current Order not exist"
);
Order memory o = orders[_orderNo];
return o;
}
function searchOrderList() external view returns (Order[] memory) {
return orderList;
}
function searchListByRest(uint256 _restNo)
external
view
returns (Order[] memory)
{
Order[] memory resultList = new Order[](orderList.length);
for (uint256 i = 0; i < orderList.length; i++) {
Order memory _order = orderList[i];
if (_order.restNo == _restNo) {
resultList[i] = _order;
}
}
return resultList;
}
}
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
contract AppealStorage {
OrderInterface private _oSt;
RecordInterface private _rSt;
UserInterface private _uSt;
address recAddr;
struct Appeal {
address user;
uint256 appealNo;
uint256 orderNo;
address witness;
address buyer;
address seller;
uint256 mortgage;
uint256 status;
uint256 appealTime;
uint256 witTakeTime;
uint256 obTakeTime;
AppealDetail detail;
}
struct AppealDetail {
address finalAppealAddr;
uint256 updateTime;
string witnessReason;
uint256 witnessAppealStatus;
string observerReason;
uint256 witnessHandleTime;
uint256 observerHandleTime;
address observerAddr;
uint256 witnessHandleReward;
uint256 observerHandleReward;
uint256 witnessHandleCredit;
uint256 observerHandleCredit;
uint256 witReward;
uint256 witSub;
uint256 witCreditR;
uint256 witCreditS;
}
mapping(uint256 => Appeal) public appeals;
mapping(uint256 => uint256) public appealIndex;
Appeal[] public appealList;
event addAppeal(uint256 _appealNo, uint256 _orderNo);
constructor(
address _r,
address _o,
address _u
) {
_rSt = RecordInterface(_r);
_oSt = OrderInterface(_o);
_uSt = UserInterface(_u);
recAddr = _r;
}
modifier onlyWit(uint256 _o) {
Appeal memory _al = appeals[_o];
require(_al.witness == msg.sender);
require(_al.buyer != msg.sender && _al.seller != msg.sender);
_;
}
modifier onlyOb(uint256 _o) {
Appeal memory _al = appeals[_o];
require(_al.detail.observerAddr == msg.sender);
require(_al.buyer != msg.sender && _al.seller != msg.sender);
_;
}
modifier onlyBOS(uint256 _o) {
OrderStorage.Order memory _r = _oSt.searchOrder(_o);
require(
_r.orderDetail.sellerAddr == msg.sender ||
_r.orderDetail.buyerAddr == msg.sender
);
_;
}
function _insert(uint256 _o, uint256 _count) internal {
OrderStorage.Order memory _or = _oSt.searchOrder(_o);
require(appeals[_o].appealNo == uint256(0));
AppealDetail memory _detail = AppealDetail({
finalAppealAddr: address(0),
updateTime: uint256(0),
witnessReason: "",
observerReason: "",
witnessAppealStatus: 0,
witnessHandleTime: uint256(0),
observerHandleTime: uint256(0),
observerAddr: address(0),
witnessHandleReward: 0,
observerHandleReward: 0,
witnessHandleCredit: 0,
observerHandleCredit: 0,
witReward: 0,
witSub: 0,
witCreditR: 0,
witCreditS: 0
});
uint256 _appealNo = block.timestamp;
Appeal memory _appeal = Appeal({
user: msg.sender,
appealNo: _appealNo,
orderNo: _o,
witness: address(0),
buyer: _or.orderDetail.buyerAddr,
seller: _or.orderDetail.sellerAddr,
mortgage: _count,
status: 1,
appealTime: block.timestamp,
witTakeTime: 0,
obTakeTime: 0,
detail: _detail
});
appeals[_o] = _appeal;
appealList.push(_appeal);
appealIndex[_o] = appealList.length - 1;
chanT(_or.orderDetail.sellerAddr, _or.orderDetail.buyerAddr, 1, 0);
emit addAppeal(_appealNo, _o);
}
function chanT(
address _seller,
address _buyer,
uint256 _t,
uint256 _r
) internal {
uint256 _tc = _rSt.getTradeCredit();
uint256 _rs = _rSt.getSubTCredit();
UserStorage.User memory _user = _uSt.searchUser(_seller);
UserStorage.TradeStats memory _tr = _user.tradeStats;
UserStorage.User memory _user2 = _uSt.searchUser(_buyer);
UserStorage.TradeStats memory _tr2 = _user2.tradeStats;
uint256 _c2 = _user2.credit;
uint256 _c = _user.credit;
if (_t == 1) {
_tr.tradeTotal = _tr.tradeTotal > 0 ? (_tr.tradeTotal - 1) : 0;
_tr2.tradeTotal = _tr2.tradeTotal > 0 ? (_tr2.tradeTotal - 1) : 0;
_c = (_c >= _tc) ? (_c - _tc) : 0;
_c2 = (_c2 >= _tc) ? (_c2 - _tc) : 0;
} else if (_t == 2) {
_tr.tradeTotal += 1;
_tr2.tradeTotal += 1;
if (_r == 1) {
_c += _tc;
_c2 = (_c2 >= _rs) ? (_c2 - _rs) : 0;
} else if (_r == 2) {
_c2 += _tc;
_c = (_c >= _rs) ? (_c - _rs) : 0;
}
}
_uSt.updateTradeStats(_seller, _tr, _c);
_uSt.updateTradeStats(_buyer, _tr2, _c2);
}
function applyAppeal(uint256 _o) external onlyBOS(_o) {
uint256 _fee = _rSt.getAppealFee();
_insert(_o, _fee);
TokenTransfer _tokenTransfer = _rSt.getERC20Address("wROSE");
_tokenTransfer.transferFrom(msg.sender, recAddr, _fee);
}
function takeWit(uint256 _o) external {
Appeal memory _al = appeals[_o];
require(_al.buyer != msg.sender && _al.seller != msg.sender);
require(_al.witness == address(0));
require(_al.status == 1);
bool _f = witOrOb(1);
require(_f);
_al.witness = msg.sender;
_al.witTakeTime = block.timestamp;
appeals[_o] = _al;
appealList[appealIndex[_o]] = _al;
}
function takeOb(uint256 _o) external {
Appeal memory _al = appeals[_o];
require(_al.buyer != msg.sender && _al.seller != msg.sender);
require(_al.status == 4 || _al.status == 5);
require(_al.detail.observerAddr == address(0));
bool _f = witOrOb(2);
require(_f);
_al.detail.observerAddr = msg.sender;
_al.obTakeTime = block.timestamp;
appeals[_o] = _al;
appealList[appealIndex[_o]] = _al;
}
function changeHandler(uint256 _o, uint256 _type) external onlyBOS(_o) {
Appeal memory _al = appeals[_o];
if (_type == 1) {
require(_al.status == 1);
require(_al.witness != address(0));
require(block.timestamp - _al.witTakeTime > 24 hours);
_al.witness = address(0);
_al.witTakeTime = 0;
} else if (_type == 2) {
require(_al.status == 4 || _al.status == 5);
require(_al.detail.observerAddr != address(0));
require(block.timestamp - _al.obTakeTime > 24 hours);
_al.detail.observerAddr = address(0);
_al.obTakeTime = 0;
}
appeals[_o] = _al;
appealList[appealIndex[_o]] = _al;
}
function witOrOb(uint256 _f) internal view returns (bool) {
UserStorage.User memory _u = _uSt.searchUser(msg.sender);
if (_u.userFlag == _f) {
return true;
}
return false;
}
function applyFinal(uint256 _o) external onlyBOS(_o) {
Appeal memory _al = appeals[_o];
require(_al.status == 2 || _al.status == 3);
require(block.timestamp - _al.detail.witnessHandleTime <= 24 hours);
chanT(_al.seller, _al.buyer, 1, 0);
uint256 _fee = _rSt.getAppealFeeFinal();
TokenTransfer _tokenTransfer = _rSt.getERC20Address("wROSE");
_tokenTransfer.transferFrom(msg.sender, recAddr, _fee);
if (_al.status == 2) {
_al.status = 4;
} else if (_al.status == 3) {
_al.status = 5;
}
_al.detail.finalAppealAddr = msg.sender;
_al.detail.updateTime = block.timestamp;
appeals[_o] = _al;
appealList[appealIndex[_o]] = _al;
}
function witnessOpt(
uint256 _o,
string memory _r,
uint256 _s
) external onlyWit(_o) {
require(_s == 2 || _s == 3);
Appeal memory _al = appeals[_o];
require(_al.status == 1);
uint256 _fee = _rSt.getAppealFee();
uint256 _rcedit = _rSt.getWitnessHandleCredit();
_al.status = _s;
_al.detail.witnessAppealStatus = _s;
_al.detail.witnessReason = _r;
_al.detail.witnessHandleTime = block.timestamp;
_al.detail.witnessHandleReward = _fee;
_al.detail.witnessHandleCredit = _rcedit;
_al.detail.witReward = _fee;
_al.detail.witCreditR = _rcedit;
_al.detail.updateTime = block.timestamp;
appeals[_o] = _al;
appealList[appealIndex[_o]] = _al;
if (_s == 2) {
if (_al.user == _al.buyer) {
_rSt.subAvaAppeal(_al.seller, _al.buyer, _al, _fee, 1, 0);
chanT(_al.seller, _al.buyer, 2, 2);
} else if (_al.user == _al.seller) {
_rSt.subAvaAppeal(_al.buyer, _al.seller, _al, _fee, 1, 0);
chanT(_al.seller, _al.buyer, 2, 1);
}
}
if (_s == 3) {
if (_al.user == _al.buyer) {
_rSt.subAvaAppeal(_al.buyer, _al.seller, _al, _fee, 1, 1);
chanT(_al.seller, _al.buyer, 2, 1);
} else if (_al.user == _al.seller) {
_rSt.subAvaAppeal(_al.seller, _al.buyer, _al, _fee, 1, 1);
chanT(_al.seller, _al.buyer, 2, 2);
}
}
}
function observerOpt(
uint256 _o,
string memory _r,
uint256 _s
) external onlyOb(_o) {
require(_s == 6 || _s == 7);
Appeal memory _appeal = appeals[_o];
require(_appeal.status == 4 || _appeal.status == 5);
uint256 _fee = _rSt.getAppealFeeFinal();
uint256 _rcedit = _rSt.getObserverHandleCredit();
_appeal.status = _s;
_appeal.detail.observerReason = _r;
_appeal.detail.observerHandleTime = block.timestamp;
_appeal.detail.observerHandleReward = _fee;
_appeal.detail.observerHandleCredit = _rcedit;
uint256 _subWC = _rSt.getSubWitCredit();
uint256 _subWF = _rSt.getSubWitFee();
if (_s == 6) {
if (_appeal.user == _appeal.buyer) {
_rSt.subAvaAppeal(
_appeal.seller,
_appeal.buyer,
_appeal,
_fee,
2,
0
);
chanT(_appeal.seller, _appeal.buyer, 2, 2);
_rSt.subFrozenTotal(_o, _appeal.buyer);
} else if (_appeal.user == _appeal.seller) {
_rSt.subAvaAppeal(
_appeal.buyer,
_appeal.seller,
_appeal,
_fee,
2,
0
);
chanT(_appeal.seller, _appeal.buyer, 2, 1);
_rSt.subFrozenTotal(_o, _appeal.seller);
}
if (_appeal.detail.witnessAppealStatus == 3) {
_appeal.detail.witSub = _subWF;
_appeal.detail.witCreditS = _subWC;
if (_appeal.detail.witnessHandleCredit >= _subWC) {
_appeal.detail.witnessHandleCredit = SafeMath.sub(
_appeal.detail.witnessHandleCredit,
_subWC
);
} else {
_appeal.detail.witnessHandleCredit = 0;
}
_rSt.subWitnessAvailable(_appeal.witness);
}
}
if (_s == 7) {
if (_appeal.user == _appeal.buyer) {
_rSt.subAvaAppeal(
_appeal.buyer,
_appeal.seller,
_appeal,
_fee,
2,
1
);
chanT(_appeal.seller, _appeal.buyer, 2, 1);
_rSt.subFrozenTotal(_o, _appeal.seller);
} else if (_appeal.user == _appeal.seller) {
_rSt.subAvaAppeal(
_appeal.seller,
_appeal.buyer,
_appeal,
_fee,
2,
1
);
chanT(_appeal.seller, _appeal.buyer, 2, 2);
_rSt.subFrozenTotal(_o, _appeal.buyer);
}
if (_appeal.detail.witnessAppealStatus == 2) {
_appeal.detail.witSub = _subWF;
_appeal.detail.witCreditS = _subWC;
if (_appeal.detail.witnessHandleCredit >= _subWC) {
_appeal.detail.witnessHandleCredit = SafeMath.sub(
_appeal.detail.witnessHandleCredit,
_subWC
);
} else {
_appeal.detail.witnessHandleCredit = 0;
}
_rSt.subWitnessAvailable(_appeal.witness);
}
}
_appeal.detail.updateTime = block.timestamp;
appeals[_o] = _appeal;
appealList[appealIndex[_o]] = _appeal;
}
function searchAppeal(uint256 _o)
external
view
returns (Appeal memory appeal)
{
return appeals[_o];
}
function searchAppealList() external view returns (Appeal[] memory) {
return appealList;
}
}
interface RecordInterface {
function getErcBalance(string memory _coinType, address _addr)
external
returns (uint256);
function getAvailableTotal(address _addr, string memory _coinType)
external
returns (uint256);
function getFrozenTotal(address _addr, string memory _coinType)
external
returns (uint256);
function addAvailableTotal(
address _addr,
string memory _coinType,
uint256 remainHoldCoin
) external;
function subAvaAppeal(
address _from,
address _to,
AppealStorage.Appeal memory _al,
uint256 _amt,
uint256 _type,
uint256 _self
) external;
function subWitnessAvailable(address _addr) external;
function getERC20Address(string memory _coinType)
external
returns (TokenTransfer);
function subFrozenTotal(uint256 _orderNo, address _addr) external;
function addRecord(
address _addr,
string memory _tradeHash,
string memory _coinType,
uint256 _hostCount,
uint256 _hostStatus,
uint256 _hostType,
uint256 _hostDirection
) external;
function getAppealFee() external view returns (uint256);
function getAppealFeeFinal() external view returns (uint256);
function getWitnessHandleReward() external view returns (uint256);
function getObserverHandleReward() external view returns (uint256);
function getWitnessHandleCredit() external view returns (uint256);
function getObserverHandleCredit() external view returns (uint256);
function getSubWitCredit() external view returns (uint256);
function getOpenTrade() external view returns (bool);
function getTradeCredit() external view returns (uint256);
function getSubTCredit() external view returns (uint256);
function getSubWitFee() external view returns (uint256);
}
interface RestInterface {
function searchRest(uint256 _restNo)
external
returns (RestStorage.Rest memory rest);
function getRestFrozenTotal(address _addr, uint256 _restNo)
external
returns (uint256);
function updateRestFinishCount(uint256 _restNo, uint256 _coinCount)
external
returns (uint256);
function addRestRemainCount(uint256 _restNo, uint256 _remainCount)
external
returns (uint256);
}
interface OrderInterface {
function searchOrder(uint256 _orderNo)
external
returns (OrderStorage.Order memory order);
}
interface UserInterface {
function searchUser(address _addr)
external
view
returns (UserStorage.User memory user);
function searchWitnessList(uint256 _userFlag)
external
returns (UserStorage.User[] memory userList);
function updateTradeStats(
address _addr,
UserStorage.TradeStats memory _tradeStats,
uint256 _credit
) external;
function updateMorgageStats(
address _addr,
UserStorage.MorgageStats memory _morgageStats
) external;
function updateUserRole(address _addr, uint256 _userFlag) external;
}
interface AppealInterface {
function searchAppeal(uint256 _o)
external
view
returns (AppealStorage.Appeal memory appeal);
}
abstract contract ReentrancyGuardRecord {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
library CountersRecord {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
{
if (counter._value == 0) {
counter._value = 10000;
}
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
{
counter._value = value - 1;
}
}
}
interface TokenTransfer {
function transfer(address recipient, uint256 amount) external;
function balanceOf(address account) external view returns (uint256);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external;
function allowance(address _owner, address _spender)
external
view
returns (uint256 remaining);
}
contract RecordStorage is Ownable, ReentrancyGuardRecord {
using CountersRecord for CountersRecord.Counter;
string constant P_COIN = 'wROSE';
mapping(string => address) coinTypeMaping;
uint256 merchantNeedCount = 100 * (10**18);
uint256 witnessNeedCount = 1000 * (10**18);
uint256 congressNeedCount = 10000 * (10**18);
uint256 appealFee = 100 * (10**18);
uint256 appealFeeFinal = 1000 * (10**18);
uint256 canWithdrawToTime = 28;
uint256 subWitFee = 100 * (10**18);
uint256 subWitCredit = 10;
uint256 witnessHandleReward = 100 * (10**18);
uint256 observerHandleReward = 1000 * (10**18);
uint256 witnessHandleCredit = 1;
uint256 observerHandleCredit = 1;
bool openTrade = false;
uint256 tradeCredit = 1;
uint256 subTCredit = 10;
mapping(address => uint256) witnessFlag;
mapping(address => uint256) congressFlag;
function setWitnessFlag(address _addr, uint256 _flag) external onlyOwner {
witnessFlag[_addr] = _flag;
if (_flag == 1) {
uint256 _amt = availableTotal[_addr][P_COIN];
require(_amt >= witnessNeedCount, "coin not enough");
_userStorage.updateUserRole(_addr, 1);
} else {
_userStorage.updateUserRole(_addr, 0);
}
}
function getWitnessFlag(address _addr) public view returns (uint256) {
return witnessFlag[_addr];
}
function setCongressFlag(address _addr, uint256 _flag) external onlyOwner {
congressFlag[_addr] = _flag;
if (_flag == 1) {
uint256 _amt = availableTotal[_addr][P_COIN];
require(_amt >= congressNeedCount, "coin not enough");
_userStorage.updateUserRole(_addr, 2);
} else {
_userStorage.updateUserRole(_addr, 0);
}
}
function getCongressFlag(address _addr) public view returns (uint256) {
return congressFlag[_addr];
}
function setCoinTypeMapping(
string calldata _coinType,
address _coinTypeAddr
) external onlyOwner {
coinTypeMaping[_coinType] = _coinTypeAddr;
}
function getCoinTypeMapping(string calldata _coinType)
public
view
returns (address)
{
return coinTypeMaping[_coinType];
}
function setMerchantNeedCount(uint256 _count) external onlyOwner {
merchantNeedCount = _count;
}
function getMerchantNeedCount() public view returns (uint256) {
return merchantNeedCount;
}
function setWitnessNeedCount(uint256 _count) external onlyOwner {
witnessNeedCount = _count;
}
function getWitnessNeedCount() public view returns (uint256) {
return witnessNeedCount;
}
function setCongressNeedCount(uint256 _count) external onlyOwner {
congressNeedCount = _count;
}
function getCongressNeedCount() public view returns (uint256) {
return congressNeedCount;
}
function setAppealFee(uint256 _count) external onlyOwner {
appealFee = _count;
}
function getAppealFee() public view returns (uint256) {
return appealFee;
}
function setAppealFeeFinal(uint256 _count) external onlyOwner {
appealFeeFinal = _count;
}
function getAppealFeeFinal() public view returns (uint256) {
return appealFeeFinal;
}
function setCanWithdrawToTime(uint256 _days) external onlyOwner {
canWithdrawToTime = _days;
}
function getCanWithdrawToTime() public view returns (uint256) {
return canWithdrawToTime;
}
function setSubWitFee(uint256 _c) external onlyOwner {
subWitFee = _c;
}
function getSubWitFee() public view returns (uint256) {
return subWitFee;
}
function setSubWitCredit(uint256 _c) external onlyOwner {
subWitCredit = _c;
}
function getSubWitCredit() public view returns (uint256) {
return subWitCredit;
}
function setWitnessHandleReward(uint256 _c) external onlyOwner {
witnessHandleReward = _c;
}
function getWitnessHandleReward() public view returns (uint256) {
return witnessHandleReward;
}
function setObserverHandleReward(uint256 _c) external onlyOwner {
observerHandleReward = _c;
}
function getObserverHandleReward() public view returns (uint256) {
return observerHandleReward;
}
function setWitnessHandleCredit(uint256 _c) external onlyOwner {
witnessHandleCredit = _c;
}
function getWitnessHandleCredit() public view returns (uint256) {
return witnessHandleCredit;
}
function setObserverHandleCredit(uint256 _c) external onlyOwner {
observerHandleCredit = _c;
}
function getObserverHandleCredit() public view returns (uint256) {
return observerHandleCredit;
}
function setOpenTrade(bool _c) external onlyOwner {
openTrade = _c;
}
function getOpenTrade() public view returns (bool) {
return openTrade;
}
function setTradeCredit(uint256 _c) external onlyOwner {
tradeCredit = _c;
}
function getTradeCredit() public view returns (uint256) {
return tradeCredit;
}
function setSubTCredit(uint256 _c) external onlyOwner {
subTCredit = _c;
}
function getSubTCredit() public view returns (uint256) {
return subTCredit;
}
function punishPerson(
address _from,
address _to,
uint256 _count
) external onlyOwner {
require(_from != address(0) && _to != address(0));
UserStorage.User memory _user = _userStorage.searchUser(_from);
require(_user.userFlag == 1 || _user.userFlag == 2, "can't punish");
uint256 _ava = availableTotal[_from][P_COIN];
uint256 _toavailab = availableTotal[_to][P_COIN];
if (_ava >= _count) {
availableTotal[_from][P_COIN] = SafeMath.sub(_ava, _count);
availableTotal[_to][P_COIN] = SafeMath.add(_toavailab, _count);
} else {
availableTotal[_from][P_COIN] = 0;
uint256 _draing = withdrawingTotal[_from][P_COIN];
if (SafeMath.add(_ava, _draing) >= _count) {
withdrawingTotal[_from][P_COIN] = SafeMath.sub(
_draing,
SafeMath.sub(_count, _ava)
);
availableTotal[_to][P_COIN] = SafeMath.add(_toavailab, _count);
} else {
withdrawingTotal[_from][P_COIN] = 0;
availableTotal[_to][P_COIN] = SafeMath.add(
_toavailab,
SafeMath.add(_ava, _draing)
);
}
}
chanRole(_from);
chanRole(_to);
}
UserInterface private _userStorage;
OrderInterface private _orderStorage;
struct Record {
uint256 recordNo;
address userAddr;
string tradeHash;
string coinType;
uint256 hostCount;
uint256 hostStatus;
uint256 hostType;
uint256 hostDirection;
uint256 hostTime;
uint256 updateTime;
}
CountersRecord.Counter private _recordNoCounter;
mapping(uint256 => Record) public records;
mapping(uint256 => uint256) public recordIndex;
Record[] public recordList;
mapping(address => mapping(string => uint256)) public availableTotal;
mapping(address => mapping(string => uint256)) public frozenTotal;
mapping(address => mapping(string => uint256)) public unfrozenTotal;
mapping(address => uint256) lastWithdrawTime;
mapping(address => mapping(uint256 => uint256)) lastWithdrawAmount;
mapping(address => mapping(string => uint256)) public withdrawingTotal;
mapping(address => mapping(uint256 => uint256)) orderSubFrozenList;
constructor(
address _usdtAddress,
address _usdcAddress,
address _coinAddress
) {
coinTypeMaping["USDT"] = _usdtAddress;
coinTypeMaping["USDC"] = _usdcAddress;
coinTypeMaping[P_COIN] = _coinAddress;
_recordNoCounter.increment();
}
function getERC20Address(string memory _coinType)
public
view
returns (TokenTransfer)
{
address _remoteAddr = coinTypeMaping[_coinType];
require(_remoteAddr != address(0));
TokenTransfer _tokenTransfer = TokenTransfer(_remoteAddr);
return _tokenTransfer;
}
event RecordAdd(
uint256 _recordNo,
address _addr,
string _tradeHash,
string _coinType,
uint256 _hostCount,
uint256 _hostStatus,
uint256 _hostType,
uint256 _hostDirection
);
event RecordApplyUnfrozen(address _addr, uint256 _amt);
event UnfrozenTotalTransfer(
address _addr,
string _coinType,
uint256 _lastAmount
);
event RecordUpdate(
address _addr,
uint256 _recordNo,
string _hash,
uint256 _hostStatus
);
address _userAddr;
address _restCAddr;
address _orderCAddr;
address _appealCAddr;
modifier onlyAuthFromAddr() {
require(_userAddr != address(0), "Invalid address call user");
require(_restCAddr != address(0), "Invalid address call rest");
require(_orderCAddr != address(0), "Invalid address call order");
require(_appealCAddr != address(0), "Invalid address call appeal");
_;
}
function authFromContract(
address _fromUser,
address _fromRest,
address _fromOrder,
address _fromAppeal
) external onlyOwner {
_userAddr = _fromUser;
_restCAddr = _fromRest;
_orderCAddr = _fromOrder;
_appealCAddr = _fromAppeal;
_userStorage = UserInterface(_userAddr);
_orderStorage = OrderInterface(_orderCAddr);
}
function _insert(
address _addr,
string memory _tradeHash,
string memory _coinType,
uint256 _hostCount,
uint256 _hostStatus,
uint256 _hostType,
uint256 _hostDirection
) internal nonReentrant returns (uint256 recordNo) {
require(_addr != address(0), "address null");
require(bytes(_coinType).length != 0, "coinType null");
require(_hostCount != uint256(0), "hostCount null");
require(_hostType != uint256(0), "hostType null");
require(_hostDirection != uint256(0), "hostDirection null");
uint256 _recordNo = _recordNoCounter.current();
require(records[_recordNo].recordNo == uint256(0), "order exist");
Record memory _record = Record({
recordNo: _recordNo,
userAddr: _addr,
tradeHash: _tradeHash,
coinType: _coinType,
hostCount: _hostCount,
hostStatus: _hostStatus,
hostType: _hostType,
hostDirection: _hostDirection,
hostTime: block.timestamp,
updateTime: 0
});
records[_recordNo] = _record;
recordList.push(_record);
recordIndex[_recordNo] = recordList.length - 1;
_recordNoCounter.increment();
emit RecordAdd(
_recordNo,
_addr,
_tradeHash,
_coinType,
_hostCount,
_hostStatus,
_hostType,
_hostDirection
);
return _recordNo;
}
function tokenEscrow(string memory _coinType, uint256 _amt) external {
require(_amt > 0, "invalid");
require(
availableTotal[msg.sender][_coinType] + _amt >
availableTotal[msg.sender][_coinType],
"Invalid transfer amount"
);
availableTotal[msg.sender][_coinType] = SafeMath.add(
availableTotal[msg.sender][_coinType],
_amt
);
uint256 _hostType = 1;
if (
keccak256(abi.encodePacked(_coinType)) ==
keccak256(abi.encodePacked(P_COIN))
) {
_hostType = 2;
UserStorage.User memory _user = _userStorage.searchUser(msg.sender);
_changeUserMorgageStats(
msg.sender,
availableTotal[msg.sender][_coinType]
);
if (
_user.userFlag == 0 &&
availableTotal[msg.sender][_coinType] >= merchantNeedCount
) {
_userStorage.updateUserRole(msg.sender, 3);
}
}
_insert(msg.sender, "", _coinType, _amt, 2, _hostType, 1);
TokenTransfer _tokenTransfer = getERC20Address(_coinType);
_tokenTransfer.transferFrom(msg.sender, address(this), _amt);
}
function addRecord(
address _addr,
string memory _tradeHash,
string memory _coinType,
uint256 _hostCount,
uint256 _hostStatus,
uint256 _hostType,
uint256 _hostDirection
) public onlyAuthFromAddr {
require(
msg.sender == _restCAddr || msg.sender == _orderCAddr,
"RedocrdStorage:Invalid from contract address"
);
frozenTotal[_addr][_coinType] = SafeMath.add(
frozenTotal[_addr][_coinType],
_hostCount
);
_insert(
_addr,
_tradeHash,
_coinType,
_hostCount,
_hostStatus,
_hostType,
_hostDirection
);
}
function addAvailableTotal(
address _addr,
string memory _coinType,
uint256 _amt
) public onlyAuthFromAddr {
require(
msg.sender == _restCAddr || msg.sender == _orderCAddr,
"Invalid address"
);
require(_amt > 0, "invalid");
uint256 _aBalance = getErcBalance(_coinType, address(this));
require(_aBalance >= _amt, "not enough");
require(frozenTotal[_addr][_coinType] >= _amt, "insufficient");
require(
SafeMath.sub(frozenTotal[_addr][_coinType], _amt) <=
frozenTotal[_addr][_coinType],
"Invalid amount"
);
frozenTotal[_addr][_coinType] = SafeMath.sub(
frozenTotal[_addr][_coinType],
_amt
);
TokenTransfer _tokenTransfer = getERC20Address(_coinType);
_tokenTransfer.transfer(_addr, _amt);
}
function getAvailableTotal(address _addr, string memory _coinType)
public
view
returns (uint256)
{
return availableTotal[_addr][_coinType];
}
function subFrozenTotal(uint256 _orderNo, address _addr)
public
onlyAuthFromAddr
{
require(
msg.sender == _orderCAddr || msg.sender == _appealCAddr,
"Invalid call"
);
OrderStorage.Order memory _order = _orderStorage.searchOrder(_orderNo);
require(_order.orderNo != uint256(0), "not exist");
address _seller = _order.orderDetail.sellerAddr;
string memory _coinType = _order.orderDetail.coinType;
uint256 _subAmount = orderSubFrozenList[_seller][_orderNo];
require(_subAmount == 0);
uint256 _frozen = frozenTotal[_seller][_coinType];
uint256 _orderCount = _order.coinCount;
require(_frozen >= _orderCount);
require(SafeMath.sub(_frozen, _orderCount) <= _frozen);
frozenTotal[_seller][_coinType] = SafeMath.sub(_frozen, _orderCount);
orderSubFrozenList[_seller][_orderNo] = _orderCount;
TokenTransfer _tokenTransfer = getERC20Address(_coinType);
_tokenTransfer.transfer(_addr, _orderCount);
}
function subAvaAppeal(
address _from,
address _to,
AppealStorage.Appeal memory _al,
uint256 _amt,
uint256 _t,
uint256 _self
) public onlyAuthFromAddr {
require(msg.sender == _appealCAddr, "Invalid call");
uint256 _available = getAvailableTotal(_from, P_COIN);
uint256 _need = 0;
address _opt = _t == 1 ? _al.witness : _al.detail.observerAddr;
if (_available >= _amt) {
_need = _amt;
} else {
_need = _available;
}
if (
(_t == 1 && _self == 0) ||
(_t == 2 && _al.detail.finalAppealAddr != _from)
) {
availableTotal[_from][P_COIN] = SafeMath.sub(
availableTotal[_from][P_COIN],
_need
);
availableTotal[_to][P_COIN] = SafeMath.add(
availableTotal[_to][P_COIN],
_need
);
_changeUserMorgageStats(_from, availableTotal[_from][P_COIN]);
_changeUserMorgageStats(_to, availableTotal[_to][P_COIN]);
}
availableTotal[_opt][P_COIN] = SafeMath.add(
availableTotal[_opt][P_COIN],
_amt
);
_changeUserMorgageStats(_opt, availableTotal[_opt][P_COIN]);
chanRole(_from);
chanRole(_to);
chanRole(_opt);
UserStorage.User memory _user = _userStorage.searchUser(_opt);
if (_t == 1) {
_user.credit = _user.credit + witnessHandleCredit;
} else if (_t == 2) {
_user.credit = _user.credit + observerHandleCredit;
}
UserStorage.TradeStats memory _tradeStats = _user.tradeStats;
_userStorage.updateTradeStats(_opt, _tradeStats, _user.credit);
}
function _changeUserMorgageStats(address _addr, uint256 _amt) internal {
UserStorage.User memory _user = _userStorage.searchUser(_addr);
UserStorage.MorgageStats memory _morgageStats = _user.morgageStats;
_morgageStats.mortgage = _amt;
_userStorage.updateMorgageStats(_addr, _morgageStats);
}
function subWitnessAvailable(address _addr) public onlyAuthFromAddr {
require(msg.sender == _appealCAddr, "Invalid call");
require(_addr != address(0), "address null");
uint256 _availableTotal = availableTotal[_addr][P_COIN];
uint256 _need = 0;
uint256 subFromDraing = 0;
if (_availableTotal >= subWitFee) {
_need = subWitFee;
availableTotal[_addr][P_COIN] = SafeMath.sub(
_availableTotal,
_need
);
} else {
availableTotal[_addr][P_COIN] = 0;
uint256 _draing = withdrawingTotal[_addr][P_COIN];
if (SafeMath.add(_availableTotal, _draing) >= subWitFee) {
_need = subWitFee;
subFromDraing = SafeMath.sub(subWitFee, _availableTotal);
withdrawingTotal[_addr][P_COIN] = SafeMath.sub(
_draing,
subFromDraing
);
} else {
_need = SafeMath.add(_draing, _availableTotal);
withdrawingTotal[_addr][P_COIN] = 0;
}
}
chanRole(_addr);
UserStorage.User memory _user = _userStorage.searchUser(_addr);
_user.credit = _user.credit >= subWitCredit
? (_user.credit - subWitCredit)
: 0;
UserStorage.TradeStats memory _tradeStats = _user.tradeStats;
_userStorage.updateTradeStats(_addr, _tradeStats, _user.credit);
TokenTransfer _tokenTransfer = getERC20Address(P_COIN);
_tokenTransfer.transfer(owner(), _need);
}
function getFrozenTotal(address _addr, string memory _coinType)
public
view
returns (uint256)
{
return frozenTotal[_addr][_coinType];
}
function applyUnfrozen(uint256 _amt) external returns (uint256) {
require(_amt > 0);
require(availableTotal[msg.sender][P_COIN] >= _amt, "Invalid amount");
require(
SafeMath.sub(availableTotal[msg.sender][P_COIN], _amt) <
availableTotal[msg.sender][P_COIN],
"Invalid amount 2"
);
lastWithdrawTime[msg.sender] = block.timestamp;
lastWithdrawAmount[msg.sender][lastWithdrawTime[msg.sender]] = _amt;
availableTotal[msg.sender][P_COIN] = SafeMath.sub(
availableTotal[msg.sender][P_COIN],
_amt
);
withdrawingTotal[msg.sender][P_COIN] = SafeMath.add(
withdrawingTotal[msg.sender][P_COIN],
_amt
);
chanRole(msg.sender);
_insert(msg.sender, "", P_COIN, _amt, 3, 3, 2);
emit RecordApplyUnfrozen(msg.sender, _amt);
return getAvailableTotal(msg.sender, P_COIN);
}
function chanRole(address _addr) internal {
uint256 _avail = availableTotal[_addr][P_COIN];
UserStorage.User memory _user = _userStorage.searchUser(_addr);
_changeUserMorgageStats(_addr, _avail);
if (
_user.userFlag == 2 &&
_avail < congressNeedCount &&
_avail >= merchantNeedCount
) {
_userStorage.updateUserRole(_addr, 3);
}
if (
_user.userFlag == 1 &&
_avail < witnessNeedCount &&
_avail >= merchantNeedCount
) {
_userStorage.updateUserRole(_addr, 3);
}
if (_user.userFlag == 0 && _avail >= merchantNeedCount) {
_userStorage.updateUserRole(_addr, 3);
}
if (_avail < merchantNeedCount) {
_userStorage.updateUserRole(_addr, 0);
}
}
function unApplyUnfrozen(address _addr) external onlyOwner {
uint256 _drawing = withdrawingTotal[_addr][P_COIN];
require(_drawing > 0, "sufficient");
withdrawingTotal[_addr][P_COIN] = 0;
availableTotal[_addr][P_COIN] = SafeMath.add(
availableTotal[_addr][P_COIN],
_drawing
);
chanRole(_addr);
}
function applyWithdraw(uint256 _recordNo) public {
Record memory _record = records[_recordNo];
require(_record.recordNo != uint256(0), "record not exist");
require(_record.userAddr == msg.sender, "record user not exist");
require(_record.hostStatus == 3, "status error");
require(
withdrawingTotal[msg.sender][P_COIN] >= _record.hostCount,
"sufficient"
);
require(
block.timestamp >= (_record.hostTime + canWithdrawToTime * 1 days),
"can't withdraw"
);
withdrawingTotal[msg.sender][P_COIN] = SafeMath.sub(
withdrawingTotal[msg.sender][P_COIN],
_record.hostCount
);
unfrozenTotal[msg.sender][P_COIN] = SafeMath.add(
unfrozenTotal[msg.sender][P_COIN],
_record.hostCount
);
_record.hostStatus = 4;
_record.updateTime = block.timestamp;
records[_recordNo] = _record;
recordList[recordIndex[_recordNo]] = _record;
emit RecordUpdate(msg.sender, _recordNo, _record.tradeHash, 4);
TokenTransfer _tokenTransfer = getERC20Address(P_COIN);
_tokenTransfer.transfer(msg.sender, _record.hostCount);
}
function unfrozenTotalSearch(address _addr, string memory _coinType)
public
view
returns (uint256)
{
require(_addr != address(0), "user address is null");
return unfrozenTotal[_addr][_coinType];
}
function getUnfrozenTotal(address _addr, string memory _coinType)
external
view
returns (uint256)
{
return unfrozenTotal[_addr][_coinType];
}
function getWithdrawingTotal(address _addr, string memory _coinType)
public
view
returns (uint256)
{
return withdrawingTotal[_addr][_coinType];
}
function getErcBalance(string memory _coinType, address _addr)
public
view
returns (uint256)
{
TokenTransfer _tokenTransfer = getERC20Address(_coinType);
return _tokenTransfer.balanceOf(_addr);
}
function _updateInfo(
address _addr,
uint256 _recordNo,
string memory _hash,
uint256 _hostStatus
) internal returns (bool) {
Record storage _record = records[_recordNo];
require(_record.userAddr == _addr);
require(_hostStatus == 1 || _hostStatus == 2, "invalid status");
if (_hostStatus != uint256(0)) {
_record.hostStatus = _hostStatus;
}
if (bytes(_hash).length != 0) {
_record.tradeHash = _hash;
}
_record.updateTime = block.timestamp;
emit RecordUpdate(_addr, _recordNo, _hash, _hostStatus);
return true;
}
function updateInfo(
address _addr,
uint256 _recordNo,
string memory _hash,
uint256 _hostStatus
) external returns (bool) {
return _updateInfo(_addr, _recordNo, _hash, _hostStatus);
}
function searchRecord(uint256 _recordNo)
external
view
returns (Record memory record)
{
return records[_recordNo];
}
function searchRecordList() external view returns (Record[] memory) {
return recordList;
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_r","internalType":"address"},{"type":"address","name":"_o","internalType":"address"},{"type":"address","name":"_u","internalType":"address"}]},{"type":"event","name":"addAppeal","inputs":[{"type":"uint256","name":"_appealNo","internalType":"uint256","indexed":false},{"type":"uint256","name":"_orderNo","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"appealIndex","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"appealNo","internalType":"uint256"},{"type":"uint256","name":"orderNo","internalType":"uint256"},{"type":"address","name":"witness","internalType":"address"},{"type":"address","name":"buyer","internalType":"address"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"mortgage","internalType":"uint256"},{"type":"uint256","name":"status","internalType":"uint256"},{"type":"uint256","name":"appealTime","internalType":"uint256"},{"type":"uint256","name":"witTakeTime","internalType":"uint256"},{"type":"uint256","name":"obTakeTime","internalType":"uint256"},{"type":"tuple","name":"detail","internalType":"struct AppealStorage.AppealDetail","components":[{"type":"address","name":"finalAppealAddr","internalType":"address"},{"type":"uint256","name":"updateTime","internalType":"uint256"},{"type":"string","name":"witnessReason","internalType":"string"},{"type":"uint256","name":"witnessAppealStatus","internalType":"uint256"},{"type":"string","name":"observerReason","internalType":"string"},{"type":"uint256","name":"witnessHandleTime","internalType":"uint256"},{"type":"uint256","name":"observerHandleTime","internalType":"uint256"},{"type":"address","name":"observerAddr","internalType":"address"},{"type":"uint256","name":"witnessHandleReward","internalType":"uint256"},{"type":"uint256","name":"observerHandleReward","internalType":"uint256"},{"type":"uint256","name":"witnessHandleCredit","internalType":"uint256"},{"type":"uint256","name":"observerHandleCredit","internalType":"uint256"},{"type":"uint256","name":"witReward","internalType":"uint256"},{"type":"uint256","name":"witSub","internalType":"uint256"},{"type":"uint256","name":"witCreditR","internalType":"uint256"},{"type":"uint256","name":"witCreditS","internalType":"uint256"}]}],"name":"appealList","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"appealNo","internalType":"uint256"},{"type":"uint256","name":"orderNo","internalType":"uint256"},{"type":"address","name":"witness","internalType":"address"},{"type":"address","name":"buyer","internalType":"address"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"mortgage","internalType":"uint256"},{"type":"uint256","name":"status","internalType":"uint256"},{"type":"uint256","name":"appealTime","internalType":"uint256"},{"type":"uint256","name":"witTakeTime","internalType":"uint256"},{"type":"uint256","name":"obTakeTime","internalType":"uint256"},{"type":"tuple","name":"detail","internalType":"struct AppealStorage.AppealDetail","components":[{"type":"address","name":"finalAppealAddr","internalType":"address"},{"type":"uint256","name":"updateTime","internalType":"uint256"},{"type":"string","name":"witnessReason","internalType":"string"},{"type":"uint256","name":"witnessAppealStatus","internalType":"uint256"},{"type":"string","name":"observerReason","internalType":"string"},{"type":"uint256","name":"witnessHandleTime","internalType":"uint256"},{"type":"uint256","name":"observerHandleTime","internalType":"uint256"},{"type":"address","name":"observerAddr","internalType":"address"},{"type":"uint256","name":"witnessHandleReward","internalType":"uint256"},{"type":"uint256","name":"observerHandleReward","internalType":"uint256"},{"type":"uint256","name":"witnessHandleCredit","internalType":"uint256"},{"type":"uint256","name":"observerHandleCredit","internalType":"uint256"},{"type":"uint256","name":"witReward","internalType":"uint256"},{"type":"uint256","name":"witSub","internalType":"uint256"},{"type":"uint256","name":"witCreditR","internalType":"uint256"},{"type":"uint256","name":"witCreditS","internalType":"uint256"}]}],"name":"appeals","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"applyAppeal","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"applyFinal","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeHandler","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"},{"type":"uint256","name":"_type","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"observerOpt","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"},{"type":"string","name":"_r","internalType":"string"},{"type":"uint256","name":"_s","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"appeal","internalType":"struct AppealStorage.Appeal","components":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"appealNo","internalType":"uint256"},{"type":"uint256","name":"orderNo","internalType":"uint256"},{"type":"address","name":"witness","internalType":"address"},{"type":"address","name":"buyer","internalType":"address"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"mortgage","internalType":"uint256"},{"type":"uint256","name":"status","internalType":"uint256"},{"type":"uint256","name":"appealTime","internalType":"uint256"},{"type":"uint256","name":"witTakeTime","internalType":"uint256"},{"type":"uint256","name":"obTakeTime","internalType":"uint256"},{"type":"tuple","name":"detail","internalType":"struct AppealStorage.AppealDetail","components":[{"type":"address","name":"finalAppealAddr","internalType":"address"},{"type":"uint256","name":"updateTime","internalType":"uint256"},{"type":"string","name":"witnessReason","internalType":"string"},{"type":"uint256","name":"witnessAppealStatus","internalType":"uint256"},{"type":"string","name":"observerReason","internalType":"string"},{"type":"uint256","name":"witnessHandleTime","internalType":"uint256"},{"type":"uint256","name":"observerHandleTime","internalType":"uint256"},{"type":"address","name":"observerAddr","internalType":"address"},{"type":"uint256","name":"witnessHandleReward","internalType":"uint256"},{"type":"uint256","name":"observerHandleReward","internalType":"uint256"},{"type":"uint256","name":"witnessHandleCredit","internalType":"uint256"},{"type":"uint256","name":"observerHandleCredit","internalType":"uint256"},{"type":"uint256","name":"witReward","internalType":"uint256"},{"type":"uint256","name":"witSub","internalType":"uint256"},{"type":"uint256","name":"witCreditR","internalType":"uint256"},{"type":"uint256","name":"witCreditS","internalType":"uint256"}]}]}],"name":"searchAppeal","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct AppealStorage.Appeal[]","components":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"appealNo","internalType":"uint256"},{"type":"uint256","name":"orderNo","internalType":"uint256"},{"type":"address","name":"witness","internalType":"address"},{"type":"address","name":"buyer","internalType":"address"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"mortgage","internalType":"uint256"},{"type":"uint256","name":"status","internalType":"uint256"},{"type":"uint256","name":"appealTime","internalType":"uint256"},{"type":"uint256","name":"witTakeTime","internalType":"uint256"},{"type":"uint256","name":"obTakeTime","internalType":"uint256"},{"type":"tuple","name":"detail","internalType":"struct AppealStorage.AppealDetail","components":[{"type":"address","name":"finalAppealAddr","internalType":"address"},{"type":"uint256","name":"updateTime","internalType":"uint256"},{"type":"string","name":"witnessReason","internalType":"string"},{"type":"uint256","name":"witnessAppealStatus","internalType":"uint256"},{"type":"string","name":"observerReason","internalType":"string"},{"type":"uint256","name":"witnessHandleTime","internalType":"uint256"},{"type":"uint256","name":"observerHandleTime","internalType":"uint256"},{"type":"address","name":"observerAddr","internalType":"address"},{"type":"uint256","name":"witnessHandleReward","internalType":"uint256"},{"type":"uint256","name":"observerHandleReward","internalType":"uint256"},{"type":"uint256","name":"witnessHandleCredit","internalType":"uint256"},{"type":"uint256","name":"observerHandleCredit","internalType":"uint256"},{"type":"uint256","name":"witReward","internalType":"uint256"},{"type":"uint256","name":"witSub","internalType":"uint256"},{"type":"uint256","name":"witCreditR","internalType":"uint256"},{"type":"uint256","name":"witCreditS","internalType":"uint256"}]}]}],"name":"searchAppealList","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"takeOb","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"takeWit","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"witnessOpt","inputs":[{"type":"uint256","name":"_o","internalType":"uint256"},{"type":"string","name":"_r","internalType":"string"},{"type":"uint256","name":"_s","internalType":"uint256"}]}]
            

Contract Creation Code

0x60806040523480156200001157600080fd5b5060405162005f3f38038062005f3f8339810160408190526200003491620000a5565b600180546001600160a01b03199081166001600160a01b03958616908117909255600080548216948616949094179093556002805484169290941691909117909255600380549091169091179055620000ef565b80516001600160a01b0381168114620000a057600080fd5b919050565b600080600060608486031215620000bb57600080fd5b620000c68462000088565b9250620000d66020850162000088565b9150620000e66040850162000088565b90509250925092565b615e4080620000ff6000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063c095d51011610071578063c095d51014610176578063ce7c8d5e14610189578063ce8efb8b1461019e578063dbd58c49146101b1578063de06bfa3146101c4578063fd33b891146101d757600080fd5b806339ccd25f146100b95780636acc4f1f146100e25780638db86746146100f75780638e6d86b51461010a578063acff868714610138578063b712479414610163575b600080fd5b6100cc6100c736600461545b565b6101ea565b6040516100d9919061568a565b60405180910390f35b6100f56100f036600461577e565b61046a565b005b6100f561010536600461577e565b61123d565b61012a61011836600461545b565b60056020526000908152604090205481565b6040519081526020016100d9565b61014b61014636600461545b565b612392565b6040516100d99c9b9a99989796959493929190615811565b6100f561017136600461545b565b61262c565b6100f561018436600461545b565b612cd8565b6101916130f9565b6040516100d9919061588e565b6100f56101ac36600461545b565b6133b3565b61014b6101bf36600461545b565b6135d6565b6100f56101d236600461545b565b6136e1565b6100f56101e53660046158f0565b613f9e565b6101f26152ae565b60008281526004602081815260409283902083516101808101855281546001600160a01b03908116825260018301548285015260028301548287015260038301548116606083015293820154841660808201526005820154841660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152845161020081018652600b830180549095168152600c83015493810193909352600d820180549195929461016087019493909290840191906102c790615912565b80601f01602080910402602001604051908101604052809291908181526020018280546102f390615912565b80156103405780601f1061031557610100808354040283529160200191610340565b820191906000526020600020905b81548152906001019060200180831161032357829003601f168201915b505050505081526020016003820154815260200160048201805461036390615912565b80601f016020809104026020016040519081016040528092919081815260200182805461038f90615912565b80156103dc5780601f106103b1576101008083540402835291602001916103dc565b820191906000526020600020905b8154815290600101906020018083116103bf57829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e0820152600c820154610100820152600d820154610120820152600e820154610140820152600f909101546101609091015290525092915050565b600083815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d820180548a97969295939461016087019493929084019161053f90615912565b80601f016020809104026020016040519081016040528092919081815260200182805461056b90615912565b80156105b85780601f1061058d576101008083540402835291602001916105b8565b820191906000526020600020905b81548152906001019060200180831161059b57829003601f168201915b50505050508152602001600382015481526020016004820180546105db90615912565b80601f016020809104026020016040519081016040528092919081815260200182805461060790615912565b80156106545780601f1061062957610100808354040283529160200191610654565b820191906000526020600020905b81548152906001019060200180831161063757829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681606001516001600160a01b03161461071857600080fd5b60808101516001600160a01b03163314801590610742575060a08101516001600160a01b03163314155b61074b57600080fd5b826002148061075a5750826003145b61076357600080fd5b600085815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061083790615912565b80601f016020809104026020016040519081016040528092919081815260200182805461086390615912565b80156108b05780601f10610885576101008083540402835291602001916108b0565b820191906000526020600020905b81548152906001019060200180831161089357829003601f168201915b50505050508152602001600382015481526020016004820180546108d390615912565b80601f01602080910402602001604051908101604052809291908181526020018280546108ff90615912565b801561094c5780601f106109215761010080835404028352916020019161094c565b820191906000526020600020905b81548152906001019060200180831161092f57829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e080830191909152600c830154610100830152600d830154610120830152600e830154610140830152600f90920154610160909101529152820151919250506001146109ea57600080fd5b600154604080516358e5ed9b60e01b815290516000926001600160a01b0316916358e5ed9b9160048083019260209291908290030181865afa158015610a34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a58919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b031663ed8aca836040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad3919061594d565b9050858360e001818152505085836101600151606001818152505086836101600151604001819052504283610160015160a0018181525050818361016001516101000181815250508083610160015161014001818152505081836101600151610180018181525050808361016001516101c001818152505042836101600151602001818152505082600460008a815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002019080519060200190610cc89291906153c2565b506060820151600382015560808201518051610cee9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050826006600560008b81526020019081526020016000205481548110610db457610db4615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c840155830151805192949192610eaa92600d87019201906153c2565b506060820151600382015560808201518051610ed09160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f90910155505060028614156110ce5782608001516001600160a01b031683600001516001600160a01b03161415611021576001805460a08501516080860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593610fd5939291899189919060009060040161597c565b600060405180830381600087803b158015610fef57600080fd5b505af1158015611003573d6000803e3d6000fd5b5050505061101c8360a00151846080015160028061473d565b6110ce565b8260a001516001600160a01b031683600001516001600160a01b031614156110ce5760018054608085015160a0860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593611086939291899189919060009060040161597c565b600060405180830381600087803b1580156110a057600080fd5b505af11580156110b4573d6000803e3d6000fd5b505050506110ce8360a0015184608001516002600161473d565b85600314156112335782608001516001600160a01b031683600001516001600160a01b031614156111885760018054608085015160a0860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d0159361113b9392918991899190819060040161597c565b600060405180830381600087803b15801561115557600080fd5b505af1158015611169573d6000803e3d6000fd5b505050506111838360a0015184608001516002600161473d565b611233565b8260a001516001600160a01b031683600001516001600160a01b03161415611233576001805460a08501516080860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d015936111ec9392918991899190819060040161597c565b600060405180830381600087803b15801561120657600080fd5b505af115801561121a573d6000803e3d6000fd5b505050506112338360a00151846080015160028061473d565b5050505050505050565b600083815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d820180548a97969295939461016087019493929084019161131290615912565b80601f016020809104026020016040519081016040528092919081815260200182805461133e90615912565b801561138b5780601f106113605761010080835404028352916020019161138b565b820191906000526020600020905b81548152906001019060200180831161136e57829003601f168201915b50505050508152602001600382015481526020016004820180546113ae90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546113da90615912565b80156114275780601f106113fc57610100808354040283529160200191611427565b820191906000526020600020905b81548152906001019060200180831161140a57829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681610160015160e001516001600160a01b0316146114f057600080fd5b60808101516001600160a01b0316331480159061151a575060a08101516001600160a01b03163314155b61152357600080fd5b82600614806115325750826007145b61153b57600080fd5b600085815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061160f90615912565b80601f016020809104026020016040519081016040528092919081815260200182805461163b90615912565b80156116885780601f1061165d57610100808354040283529160200191611688565b820191906000526020600020905b81548152906001019060200180831161166b57829003601f168201915b50505050508152602001600382015481526020016004820180546116ab90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546116d790615912565b80156117245780601f106116f957610100808354040283529160200191611724565b820191906000526020600020905b81548152906001019060200180831161170757829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e080830191909152600c830154610100830152600d830154610120830152600e830154610140830152600f9092015461016090910152915282015191925050600414806117c857508060e001516005145b6117d157600080fd5b60015460408051632c96c35760e11b815290516000926001600160a01b03169163592d86ae9160048083019260209291908290030181865afa15801561181b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183f919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b03166327c34aed6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611896573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ba919061594d565b60e0840187905261016080850180516080018a905280514260c09091015280516101200185905251018190526001546040805163758027dd60e11b815290519293506000926001600160a01b039092169163eb004fba916004808201926020929091908290030181865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b0316636dc0ee556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d5919061594d565b90508760061415611ce25784608001516001600160a01b031685600001516001600160a01b03161415611afc5760015460a08601516080870151604051632ad8d01560e01b81526001600160a01b0390931692632ad8d01592611a469290918a908a9060029060009060040161597c565b600060405180830381600087803b158015611a6057600080fd5b505af1158015611a74573d6000803e3d6000fd5b50505050611a8d8560a00151866080015160028061473d565b60015460808601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611adf57600080fd5b505af1158015611af3573d6000803e3d6000fd5b50505050611c15565b8460a001516001600160a01b031685600001516001600160a01b03161415611c1557600154608086015160a0870151604051632ad8d01560e01b81526001600160a01b0390931692632ad8d01592611b629290918a908a9060029060009060040161597c565b600060405180830381600087803b158015611b7c57600080fd5b505af1158015611b90573d6000803e3d6000fd5b50505050611baa8560a0015186608001516002600161473d565b60015460a08601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611bfc57600080fd5b505af1158015611c10573d6000803e3d6000fd5b505050505b8461016001516060015160031415611ce257610160850180516101a00182905280516101e0018390525161014001518211611c6e57611c5e856101600151610140015183614b3d565b6101608601516101400152611c7e565b6101608501516000610140909101525b60015460608601516040516363029b9f60e11b81526001600160a01b03918216600482015291169063c605373e90602401600060405180830381600087803b158015611cc957600080fd5b505af1158015611cdd573d6000803e3d6000fd5b505050505b8760071415611fe95784608001516001600160a01b031685600001516001600160a01b03161415611e065760018054608087015160a0880151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593611d4f9392918b918b9160029160040161597c565b600060405180830381600087803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050611d978560a0015186608001516002600161473d565b60015460a08601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611de957600080fd5b505af1158015611dfd573d6000803e3d6000fd5b50505050611f1c565b8460a001516001600160a01b031685600001516001600160a01b03161415611f1c576001805460a08701516080880151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593611e6a9392918b918b9160029160040161597c565b600060405180830381600087803b158015611e8457600080fd5b505af1158015611e98573d6000803e3d6000fd5b50505050611eb18560a00151866080015160028061473d565b60015460808601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611f0357600080fd5b505af1158015611f17573d6000803e3d6000fd5b505050505b8461016001516060015160021415611fe957610160850180516101a00182905280516101e0018390525161014001518211611f7557611f65856101600151610140015183614b3d565b6101608601516101400152611f85565b6101608501516000610140909101525b60015460608601516040516363029b9f60e11b81526001600160a01b03918216600482015291169063c605373e90602401600060405180830381600087803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b505050505b610160850180514260209182015260008c81526004808352604091829020895181546001600160a01b03199081166001600160a01b03928316178355858c01516001840155848c0151600284015560608c0151600384018054831691841691909117905560808c0151938301805482169483169490941790935560a08b0151600583018054851691831691909117905560c08b0151600683015560e08b015160078301556101008b015160088301556101208b015160098301556101408b0151600a83015594518051600b83018054909416961695909517825584840151600c8201559184015180518a9593946120e792600d8701929101906153c2565b50606082015160038201556080820151805161210d9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050846006600560008d815260200190815260200160002054815481106121d3576121d3615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c8401558301518051929491926122c992600d87019201906153c2565b5060608201516003820155608082015180516122ef9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f90910155505050505050505050505050565b60046020528060005260406000206000915090508060000160009054906101000a90046001600160a01b0316908060010154908060020154908060030160009054906101000a90046001600160a01b0316908060040160009054906101000a90046001600160a01b0316908060050160009054906101000a90046001600160a01b03169080600601549080600701549080600801549080600901549080600a01549080600b01604051806102000160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201805461248d90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546124b990615912565b80156125065780601f106124db57610100808354040283529160200191612506565b820191906000526020600020905b8154815290600101906020018083116124e957829003601f168201915b505050505081526020016003820154815260200160048201805461252990615912565b80601f016020809104026020016040519081016040528092919081815260200182805461255590615912565b80156125a25780601f10612577576101008083540402835291602001916125a2565b820191906000526020600020905b81548152906001019060200180831161258557829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e0820152600c820154610100820152600d820154610120820152600e820154610140820152600f909101546101609091015290508c565b600081815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061270090615912565b80601f016020809104026020016040519081016040528092919081815260200182805461272c90615912565b80156127795780601f1061274e57610100808354040283529160200191612779565b820191906000526020600020905b81548152906001019060200180831161275c57829003601f168201915b505050505081526020016003820154815260200160048201805461279c90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546127c890615912565b80156128155780601f106127ea57610100808354040283529160200191612815565b820191906000526020600020905b8154815290600101906020018083116127f857829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681608001516001600160a01b0316141580156128ea575060a08101516001600160a01b03163314155b6128f357600080fd5b60608101516001600160a01b03161561290b57600080fd5b8060e0015160011461291c57600080fd5b60006129286001614b50565b90508061293457600080fd5b3360608301908152426101208401908152600085815260046020818152604092839020875181546001600160a01b03199081166001600160a01b03928316178355838a01516001840155858a01516002840155965160038301805489169183169190911790556080890151938201805488169482169490941790935560a0880151600582018054881691851691909117905560c0880151600682015560e08801516007820155610100880151600882015593516009850155610140870151600a8501556101608701518051600b86018054909716931692909217855581810151600c85015591810151805187959293612a3492600d8701929101906153c2565b506060820151600382015560808201518051612a5a9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050816006600560008681526020019081526020016000205481548110612b2057612b20615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c840155830151805192949192612c1692600d87019201906153c2565b506060820151600382015560808201518051612c3c9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f909101555050505050565b600081815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d82018054919592946101608701949093929084019190612dac90615912565b80601f0160208091040260200160405190810160405280929190818152602001828054612dd890615912565b8015612e255780601f10612dfa57610100808354040283529160200191612e25565b820191906000526020600020905b815481529060010190602001808311612e0857829003601f168201915b5050505050815260200160038201548152602001600482018054612e4890615912565b80601f0160208091040260200160405190810160405280929190818152602001828054612e7490615912565b8015612ec15780601f10612e9657610100808354040283529160200191612ec1565b820191906000526020600020905b815481529060010190602001808311612ea457829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681608001516001600160a01b031614158015612f96575060a08101516001600160a01b03163314155b612f9f57600080fd5b8060e0015160041480612fb657508060e001516005145b612fbf57600080fd5b61016081015160e001516001600160a01b031615612fdc57600080fd5b6000612fe86002614b50565b905080612ff457600080fd5b610160820180513360e091820152426101408501908152600086815260046020818152604092839020885181546001600160a01b03199081166001600160a01b03928316178355838b01516001840155858b0151600284015560608b0151600384018054831691841691909117905560808b0151948301805482169583169590951790945560a08a0151600583018054861691831691909117905560c08a01516006830155958901516007820155610100890151600882015561012089015160098201559351600a85015594518051600b85018054909316951694909417815583850151600c8401559083015180518795939493612a3492600d8701929101906153c2565b60606006805480602002602001604051908101604052809291908181526020016000905b828210156133aa5760008481526020908190206040805161018081018252601b860290920180546001600160a01b0390811684526001820154848601526002820154848401526003820154811660608501526004820154811660808501526005820154811660a0850152600682015460c0850152600782015460e085015260088201546101008501526009820154610120850152600a820154610140850152825161020081018452600b830180549092168152600c83015495810195909552600d8201805494959294610160870194840191906131f990615912565b80601f016020809104026020016040519081016040528092919081815260200182805461322590615912565b80156132725780601f1061324757610100808354040283529160200191613272565b820191906000526020600020905b81548152906001019060200180831161325557829003601f168201915b505050505081526020016003820154815260200160048201805461329590615912565b80601f01602080910402602001604051908101604052809291908181526020018280546132c190615912565b801561330e5780601f106132e35761010080835404028352916020019161330e565b820191906000526020600020905b8154815290600101906020018083116132f157829003601f168201915b505050918352505060058201546020808301919091526006830154604083015260078301546001600160a01b0316606083015260088301546080830152600983015460a0830152600a83015460c0830152600b83015460e0830152600c830154610100830152600d830154610120830152600e830154610140830152600f9092015461016090910152915291835250600192909201910161311d565b50505050905090565b600080546040516362bb335f60e11b8152600481018490528392916001600160a01b03169063c57666be906024016000604051808303816000875af1158015613400573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134289190810190615af5565b610120810151602001519091506001600160a01b03163314806134595750610120810151516001600160a01b031633145b61346257600080fd5b600154604080516358e5ed9b60e01b815290516000926001600160a01b0316916358e5ed9b9160048083019260209291908290030181865afa1580156134ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134d0919061594d565b90506134dc8482614be5565b600154604051630bc67f9b60e01b815260206004820152600560248201526477524f534560d81b60448201526000916001600160a01b031690630bc67f9b906064016020604051808303816000875af115801561353d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135619190615be4565b6003546040516323b872dd60e01b81523360048201526001600160a01b039182166024820152604481018590529192508216906323b872dd90606401600060405180830381600087803b1580156135b757600080fd5b505af11580156135cb573d6000803e3d6000fd5b505050505050505050565b600681815481106135e657600080fd5b90600052602060002090601b02016000915090508060000160009054906101000a90046001600160a01b0316908060010154908060020154908060030160009054906101000a90046001600160a01b0316908060040160009054906101000a90046001600160a01b0316908060050160009054906101000a90046001600160a01b03169080600601549080600701549080600801549080600901549080600a01549080600b01604051806102000160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201805461248d90615912565b600080546040516362bb335f60e11b8152600481018490528392916001600160a01b03169063c57666be906024016000604051808303816000875af115801561372e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137569190810190615af5565b610120810151602001519091506001600160a01b03163314806137875750610120810151516001600160a01b031633145b61379057600080fd5b600083815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061386490615912565b80601f016020809104026020016040519081016040528092919081815260200182805461389090615912565b80156138dd5780601f106138b2576101008083540402835291602001916138dd565b820191906000526020600020905b8154815290600101906020018083116138c057829003601f168201915b505050505081526020016003820154815260200160048201805461390090615912565b80601f016020809104026020016040519081016040528092919081815260200182805461392c90615912565b80156139795780601f1061394e57610100808354040283529160200191613979565b820191906000526020600020905b81548152906001019060200180831161395c57829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e080830191909152600c830154610100830152600d830154610120830152600e830154610140830152600f909201546101609091015291528201519192505060021480613a1d57508060e001516003145b613a2657600080fd5b6201518081610160015160a0015142613a3f9190615c17565b1115613a4a57600080fd5b613a608160a0015182608001516001600061473d565b60015460408051632c96c35760e11b815290516000926001600160a01b03169163592d86ae9160048083019260209291908290030181865afa158015613aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ace919061594d565b600154604051630bc67f9b60e01b815260206004820152600560248201526477524f534560d81b60448201529192506000916001600160a01b0390911690630bc67f9b906064016020604051808303816000875af1158015613b34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b589190615be4565b6003546040516323b872dd60e01b81523360048201526001600160a01b039182166024820152604481018590529192508216906323b872dd90606401600060405180830381600087803b158015613bae57600080fd5b505af1158015613bc2573d6000803e3d6000fd5b505050508260e0015160021415613bdf57600460e0840152613bf4565b8260e0015160031415613bf457600560e08401525b6101608301805133905280514260209182015260008881526004808352604091829020875181546001600160a01b03199081166001600160a01b03928316178355858a01516001840155848a0151600284015560608a0151600384018054831691841691909117905560808a0151938301805482169483169490941790935560a0890151600583018054851691831691909117905560c0890151600683015560e0890151600783015561010089015160088301556101208901516009830155610140890151600a83015594518051600b83018054909416961695909517825584840151600c82015591840151805188959394613cf792600d8701929101906153c2565b506060820151600382015560808201518051613d1d9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050826006600560008981526020019081526020016000205481548110613de357613de3615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c840155830151805192949192613ed992600d87019201906153c2565b506060820151600382015560808201518051613eff9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f909101555050505050505050565b600080546040516362bb335f60e11b8152600481018590528492916001600160a01b03169063c57666be906024016000604051808303816000875af1158015613feb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526140139190810190615af5565b610120810151602001519091506001600160a01b03163314806140445750610120810151516001600160a01b031633145b61404d57600080fd5b600084815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061412190615912565b80601f016020809104026020016040519081016040528092919081815260200182805461414d90615912565b801561419a5780601f1061416f5761010080835404028352916020019161419a565b820191906000526020600020905b81548152906001019060200180831161417d57829003601f168201915b50505050508152602001600382015481526020016004820180546141bd90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546141e990615912565b80156142365780601f1061420b57610100808354040283529160200191614236565b820191906000526020600020905b81548152906001019060200180831161421957829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e0820152600c820154610100820152600d820154610120820152600e820154610140820152600f909101546101609091015290525090506001841415614324578060e001516001146142da57600080fd5b60608101516001600160a01b03166142f157600080fd5b62015180816101200151426143069190615c17565b1161431057600080fd5b60006060820181905261012082015261439f565b836002141561439f578060e001516004148061434457508060e001516005145b61434d57600080fd5b61016081015160e001516001600160a01b031661436957600080fd5b620151808161014001514261437e9190615c17565b1161438857600080fd5b610160810151600060e09091018190526101408201525b600085815260046020818152604092839020845181546001600160a01b03199081166001600160a01b03928316178355868401516001840155868601516002840155606087015160038401805483169184169190911790556080870151948301805482169583169590951790945560a0860151600583018054861691831691909117905560c0860151600683015560e0860151600783015561010086015160088301556101208601516009830155610140860151600a8301556101608601518051600b84018054909616921691909117845580830151600c83015593840151805186959294929361449792600d8701929101906153c2565b5060608201516003820155608082015180516144bd9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0155505090505080600660056000888152602001908152602001600020548154811061458357614583615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c84015583015180519294919261467992600d87019201906153c2565b50606082015160038201556080820151805161469f9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f9091015550505050505050565b60015460408051635c7cee6360e01b815290516000926001600160a01b031691635c7cee639160048083019260209291908290030181865afa158015614787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147ab919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b031663c941455c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614802573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614826919061594d565b600254604051639bd7417f60e01b81526001600160a01b03898116600483015292935060009290911690639bd7417f90602401600060405180830381865afa158015614876573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261489e9190810190615d01565b60e0810151600254604051639bd7417f60e01b81526001600160a01b038a811660048301529394509192600092911690639bd7417f90602401600060405180830381865afa1580156148f4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261491c9190810190615d01565b60e081015160a08083015190860151929350909160018a14156149ae578451614946576000614954565b845161495490600190615c17565b85528251614963576000614971565b825161497190600190615c17565b83528781101561498257600061498c565b61498c8882615c17565b90508782101561499d5760006149a7565b6149a78883615c17565b9150614a41565b8960021415614a41576001856000018181516149ca9190615df2565b905250825160019084906149df908390615df2565b9052506001891415614a10576149f58882615df2565b905086821015614a065760006149a7565b6149a78783615c17565b8860021415614a4157614a238883615df2565b915086811015614a34576000614a3e565b614a3e8782615c17565b90505b6002546040516316a1e96960e31b81526001600160a01b038e811660048301528751602483015260208801516044830152606482018490529091169063b50f4b4890608401600060405180830381600087803b158015614aa057600080fd5b505af1158015614ab4573d6000803e3d6000fd5b50506002546040516316a1e96960e31b81526001600160a01b038f81166004830152875160248301526020880151604483015260648201879052909116925063b50f4b489150608401600060405180830381600087803b158015614b1757600080fd5b505af1158015614b2b573d6000803e3d6000fd5b50505050505050505050505050505050565b6000614b498284615c17565b9392505050565b600254604051639bd7417f60e01b815233600482015260009182916001600160a01b0390911690639bd7417f90602401600060405180830381865afa158015614b9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614bc59190810190615d01565b90508281608001511415614bdc5750600192915050565b50600092915050565b600080546040516362bb335f60e11b8152600481018590526001600160a01b039091169063c57666be906024016000604051808303816000875af1158015614c31573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614c599190810190615af5565b60008481526004602052604090206001015490915015614c7857600080fd5b600060405180610200016040528060006001600160a01b031681526020016000815260200160405180602001604052806000815250815260200160008152602001604051806020016040528060008152508152602001600081526020016000815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815250905060004290506000604051806101800160405280336001600160a01b0316815260200183815260200187815260200160006001600160a01b03168152602001856101200151600001516001600160a01b03168152602001856101200151602001516001600160a01b03168152602001868152602001600181526020014281526020016000815260200160008152602001848152509050806004600088815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002019080519060200190614f279291906153c2565b506060820151600382015560808201518051614f4d9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0155505090505060068190806001815401808255809150506001900390600052602060002090601b020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020190805190602001906151729291906153c2565b5060608201516003820155608082015180516151989160048401916020909101906153c2565b5060a0820151600582015560c082015160068083019190915560e08301516007830180546001600160a01b0319166001600160a01b0390921691909117905561010083015160088301556101208301516009830155610140830151600a830155610160830151600b830155610180830151600c8301556101a0830151600d8301556101c0830151600e8301556101e090920151600f9091015554615240925060019150615c17565b600087815260056020908152604082209290925561012086015191820151915161526d929160019061473d565b60408051838152602081018890527f6b787c191423cbfdb42197fdc3357a6627229f66a0bccccba5d1841388364604910160405180910390a1505050505050565b60405180610180016040528060006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016153bd60405180610200016040528060006001600160a01b0316815260200160008152602001606081526020016000815260200160608152602001600081526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b905290565b8280546153ce90615912565b90600052602060002090601f0160209004810192826153f05760008555615436565b82601f1061540957805160ff1916838001178555615436565b82800160010185558215615436579182015b8281111561543657825182559160200191906001019061541b565b50615442929150615446565b5090565b5b808211156154425760008155600101615447565b60006020828403121561546d57600080fd5b5035919050565b60005b8381101561548f578181015183820152602001615477565b8381111561549e576000848401525b50505050565b600081518084526154bc816020860160208601615474565b601f01601f19169290920160200192915050565b80516001600160a01b031682526000610200602083015160208501526040830151816040860152615503828601826154a4565b915050606083015160608501526080830151848203608086015261552782826154a4565b91505060a083015160a085015260c083015160c085015260e083015161555860e08601826001600160a01b03169052565b50610100838101519085015261012080840151908501526101408084015190850152610160808401519085015261018080840151908501526101a080840151908501526101c080840151908501526101e09283015192909301919091525090565b80516001600160a01b031682526000610180602083015160208501526040830151604085015260608301516155f960608601826001600160a01b03169052565b50608083015161561460808601826001600160a01b03169052565b5060a083015161562f60a08601826001600160a01b03169052565b5060c083015160c085015260e083015160e0850152610100808401518186015250610120808401518186015250610140808401518186015250610160808401518282870152615680838701826154d0565b9695505050505050565b602081526000614b4960208301846155b9565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156156d7576156d761569d565b60405290565b604051610140810167ffffffffffffffff811182821017156156d7576156d761569d565b604051610120810167ffffffffffffffff811182821017156156d7576156d761569d565b604051601f8201601f1916810167ffffffffffffffff8111828210171561574e5761574e61569d565b604052919050565b600067ffffffffffffffff8211156157705761577061569d565b50601f01601f191660200190565b60008060006060848603121561579357600080fd5b83359250602084013567ffffffffffffffff8111156157b157600080fd5b8401601f810186136157c257600080fd5b80356157d56157d082615756565b615725565b8181528760208385010111156157ea57600080fd5b81602084016020830137600060208383010152809450505050604084013590509250925092565b600060018060a01b03808f1683528d60208401528c6040840152808c166060840152808b166080840152808a1660a0840152508760c08301528660e083015285610100830152846101208301528361014083015261018061016083015261587c6101808301846154d0565b9e9d5050505050505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156158e357603f198886030184526158d18583516155b9565b945092850192908501906001016158b5565b5092979650505050505050565b6000806040838503121561590357600080fd5b50508035926020909101359150565b600181811c9082168061592657607f821691505b6020821081141561594757634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561595f57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0387811682528616602082015260c0604082018190526000906159a8908301876155b9565b606083019590955250608081019290925260a0909101529392505050565b6001600160a01b03811681146159db57600080fd5b50565b80516159e9816159c6565b919050565b600082601f8301126159ff57600080fd5b8151615a0d6157d082615756565b818152846020838601011115615a2257600080fd5b615a33826020830160208701615474565b949350505050565b60006101008284031215615a4e57600080fd5b615a566156b3565b9050615a61826159de565b8152615a6f602083016159de565b6020820152604082015167ffffffffffffffff80821115615a8f57600080fd5b615a9b858386016159ee565b6040840152606084015160608401526080840151608084015260a084015160a084015260c0840151915080821115615ad257600080fd5b50615adf848285016159ee565b60c08301525060e082015160e082015292915050565b600060208284031215615b0757600080fd5b815167ffffffffffffffff80821115615b1f57600080fd5b908301906101408286031215615b3457600080fd5b615b3c6156dd565b615b45836159de565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015182811115615b8b57600080fd5b615b97878286016159ee565b60c08301525060e083015160e08201526101008084015181830152506101208084015183811115615bc757600080fd5b615bd388828701615a3b565b918301919091525095945050505050565b600060208284031215615bf657600080fd5b8151614b49816159c6565b634e487b7160e01b600052601160045260246000fd5b600082821015615c2957615c29615c01565b500390565b600060408284031215615c4057600080fd5b6040516040810181811067ffffffffffffffff82111715615c6357615c6361569d565b604052825181526020928301519281019290925250919050565b600060e08284031215615c8f57600080fd5b60405160e0810181811067ffffffffffffffff82111715615cb257615cb261569d565b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201525092915050565b600060208284031215615d1357600080fd5b815167ffffffffffffffff80821115615d2b57600080fd5b908301906102008286031215615d4057600080fd5b615d48615701565b615d51836159de565b8152602083015182811115615d6557600080fd5b615d71878286016159ee565b602083015250604083015182811115615d8957600080fd5b615d95878286016159ee565b604083015250606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152615dd08660e08501615c2e565b60e0820152615de3866101208501615c7d565b61010082015295945050505050565b60008219821115615e0557615e05615c01565b50019056fea26469706673582212204cccb338c05fa54f4a8da06be187a39fb14fbe533f0d3d60d86ff80f4f3ba7ff64736f6c634300080b0033000000000000000000000000a81c9070cdde315180fcb14b783345f77e0871380000000000000000000000006c76489e86e1f9a1c3f51064b3f4f6435e3ba6bd000000000000000000000000307e9d89bdc72336d70c50e6abc1cae76cbdfc5c

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100b45760003560e01c8063c095d51011610071578063c095d51014610176578063ce7c8d5e14610189578063ce8efb8b1461019e578063dbd58c49146101b1578063de06bfa3146101c4578063fd33b891146101d757600080fd5b806339ccd25f146100b95780636acc4f1f146100e25780638db86746146100f75780638e6d86b51461010a578063acff868714610138578063b712479414610163575b600080fd5b6100cc6100c736600461545b565b6101ea565b6040516100d9919061568a565b60405180910390f35b6100f56100f036600461577e565b61046a565b005b6100f561010536600461577e565b61123d565b61012a61011836600461545b565b60056020526000908152604090205481565b6040519081526020016100d9565b61014b61014636600461545b565b612392565b6040516100d99c9b9a99989796959493929190615811565b6100f561017136600461545b565b61262c565b6100f561018436600461545b565b612cd8565b6101916130f9565b6040516100d9919061588e565b6100f56101ac36600461545b565b6133b3565b61014b6101bf36600461545b565b6135d6565b6100f56101d236600461545b565b6136e1565b6100f56101e53660046158f0565b613f9e565b6101f26152ae565b60008281526004602081815260409283902083516101808101855281546001600160a01b03908116825260018301548285015260028301548287015260038301548116606083015293820154841660808201526005820154841660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152845161020081018652600b830180549095168152600c83015493810193909352600d820180549195929461016087019493909290840191906102c790615912565b80601f01602080910402602001604051908101604052809291908181526020018280546102f390615912565b80156103405780601f1061031557610100808354040283529160200191610340565b820191906000526020600020905b81548152906001019060200180831161032357829003601f168201915b505050505081526020016003820154815260200160048201805461036390615912565b80601f016020809104026020016040519081016040528092919081815260200182805461038f90615912565b80156103dc5780601f106103b1576101008083540402835291602001916103dc565b820191906000526020600020905b8154815290600101906020018083116103bf57829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e0820152600c820154610100820152600d820154610120820152600e820154610140820152600f909101546101609091015290525092915050565b600083815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d820180548a97969295939461016087019493929084019161053f90615912565b80601f016020809104026020016040519081016040528092919081815260200182805461056b90615912565b80156105b85780601f1061058d576101008083540402835291602001916105b8565b820191906000526020600020905b81548152906001019060200180831161059b57829003601f168201915b50505050508152602001600382015481526020016004820180546105db90615912565b80601f016020809104026020016040519081016040528092919081815260200182805461060790615912565b80156106545780601f1061062957610100808354040283529160200191610654565b820191906000526020600020905b81548152906001019060200180831161063757829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681606001516001600160a01b03161461071857600080fd5b60808101516001600160a01b03163314801590610742575060a08101516001600160a01b03163314155b61074b57600080fd5b826002148061075a5750826003145b61076357600080fd5b600085815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061083790615912565b80601f016020809104026020016040519081016040528092919081815260200182805461086390615912565b80156108b05780601f10610885576101008083540402835291602001916108b0565b820191906000526020600020905b81548152906001019060200180831161089357829003601f168201915b50505050508152602001600382015481526020016004820180546108d390615912565b80601f01602080910402602001604051908101604052809291908181526020018280546108ff90615912565b801561094c5780601f106109215761010080835404028352916020019161094c565b820191906000526020600020905b81548152906001019060200180831161092f57829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e080830191909152600c830154610100830152600d830154610120830152600e830154610140830152600f90920154610160909101529152820151919250506001146109ea57600080fd5b600154604080516358e5ed9b60e01b815290516000926001600160a01b0316916358e5ed9b9160048083019260209291908290030181865afa158015610a34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a58919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b031663ed8aca836040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad3919061594d565b9050858360e001818152505085836101600151606001818152505086836101600151604001819052504283610160015160a0018181525050818361016001516101000181815250508083610160015161014001818152505081836101600151610180018181525050808361016001516101c001818152505042836101600151602001818152505082600460008a815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002019080519060200190610cc89291906153c2565b506060820151600382015560808201518051610cee9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050826006600560008b81526020019081526020016000205481548110610db457610db4615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c840155830151805192949192610eaa92600d87019201906153c2565b506060820151600382015560808201518051610ed09160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f90910155505060028614156110ce5782608001516001600160a01b031683600001516001600160a01b03161415611021576001805460a08501516080860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593610fd5939291899189919060009060040161597c565b600060405180830381600087803b158015610fef57600080fd5b505af1158015611003573d6000803e3d6000fd5b5050505061101c8360a00151846080015160028061473d565b6110ce565b8260a001516001600160a01b031683600001516001600160a01b031614156110ce5760018054608085015160a0860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593611086939291899189919060009060040161597c565b600060405180830381600087803b1580156110a057600080fd5b505af11580156110b4573d6000803e3d6000fd5b505050506110ce8360a0015184608001516002600161473d565b85600314156112335782608001516001600160a01b031683600001516001600160a01b031614156111885760018054608085015160a0860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d0159361113b9392918991899190819060040161597c565b600060405180830381600087803b15801561115557600080fd5b505af1158015611169573d6000803e3d6000fd5b505050506111838360a0015184608001516002600161473d565b611233565b8260a001516001600160a01b031683600001516001600160a01b03161415611233576001805460a08501516080860151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d015936111ec9392918991899190819060040161597c565b600060405180830381600087803b15801561120657600080fd5b505af115801561121a573d6000803e3d6000fd5b505050506112338360a00151846080015160028061473d565b5050505050505050565b600083815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d820180548a97969295939461016087019493929084019161131290615912565b80601f016020809104026020016040519081016040528092919081815260200182805461133e90615912565b801561138b5780601f106113605761010080835404028352916020019161138b565b820191906000526020600020905b81548152906001019060200180831161136e57829003601f168201915b50505050508152602001600382015481526020016004820180546113ae90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546113da90615912565b80156114275780601f106113fc57610100808354040283529160200191611427565b820191906000526020600020905b81548152906001019060200180831161140a57829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681610160015160e001516001600160a01b0316146114f057600080fd5b60808101516001600160a01b0316331480159061151a575060a08101516001600160a01b03163314155b61152357600080fd5b82600614806115325750826007145b61153b57600080fd5b600085815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061160f90615912565b80601f016020809104026020016040519081016040528092919081815260200182805461163b90615912565b80156116885780601f1061165d57610100808354040283529160200191611688565b820191906000526020600020905b81548152906001019060200180831161166b57829003601f168201915b50505050508152602001600382015481526020016004820180546116ab90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546116d790615912565b80156117245780601f106116f957610100808354040283529160200191611724565b820191906000526020600020905b81548152906001019060200180831161170757829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e080830191909152600c830154610100830152600d830154610120830152600e830154610140830152600f9092015461016090910152915282015191925050600414806117c857508060e001516005145b6117d157600080fd5b60015460408051632c96c35760e11b815290516000926001600160a01b03169163592d86ae9160048083019260209291908290030181865afa15801561181b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183f919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b03166327c34aed6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611896573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ba919061594d565b60e0840187905261016080850180516080018a905280514260c09091015280516101200185905251018190526001546040805163758027dd60e11b815290519293506000926001600160a01b039092169163eb004fba916004808201926020929091908290030181865afa158015611936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195a919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b0316636dc0ee556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d5919061594d565b90508760061415611ce25784608001516001600160a01b031685600001516001600160a01b03161415611afc5760015460a08601516080870151604051632ad8d01560e01b81526001600160a01b0390931692632ad8d01592611a469290918a908a9060029060009060040161597c565b600060405180830381600087803b158015611a6057600080fd5b505af1158015611a74573d6000803e3d6000fd5b50505050611a8d8560a00151866080015160028061473d565b60015460808601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611adf57600080fd5b505af1158015611af3573d6000803e3d6000fd5b50505050611c15565b8460a001516001600160a01b031685600001516001600160a01b03161415611c1557600154608086015160a0870151604051632ad8d01560e01b81526001600160a01b0390931692632ad8d01592611b629290918a908a9060029060009060040161597c565b600060405180830381600087803b158015611b7c57600080fd5b505af1158015611b90573d6000803e3d6000fd5b50505050611baa8560a0015186608001516002600161473d565b60015460a08601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611bfc57600080fd5b505af1158015611c10573d6000803e3d6000fd5b505050505b8461016001516060015160031415611ce257610160850180516101a00182905280516101e0018390525161014001518211611c6e57611c5e856101600151610140015183614b3d565b6101608601516101400152611c7e565b6101608501516000610140909101525b60015460608601516040516363029b9f60e11b81526001600160a01b03918216600482015291169063c605373e90602401600060405180830381600087803b158015611cc957600080fd5b505af1158015611cdd573d6000803e3d6000fd5b505050505b8760071415611fe95784608001516001600160a01b031685600001516001600160a01b03161415611e065760018054608087015160a0880151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593611d4f9392918b918b9160029160040161597c565b600060405180830381600087803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050611d978560a0015186608001516002600161473d565b60015460a08601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611de957600080fd5b505af1158015611dfd573d6000803e3d6000fd5b50505050611f1c565b8460a001516001600160a01b031685600001516001600160a01b03161415611f1c576001805460a08701516080880151604051632ad8d01560e01b81526001600160a01b0390931693632ad8d01593611e6a9392918b918b9160029160040161597c565b600060405180830381600087803b158015611e8457600080fd5b505af1158015611e98573d6000803e3d6000fd5b50505050611eb18560a00151866080015160028061473d565b60015460808601516040516301b7257760e41b8152600481018d90526001600160a01b039182166024820152911690631b72577090604401600060405180830381600087803b158015611f0357600080fd5b505af1158015611f17573d6000803e3d6000fd5b505050505b8461016001516060015160021415611fe957610160850180516101a00182905280516101e0018390525161014001518211611f7557611f65856101600151610140015183614b3d565b6101608601516101400152611f85565b6101608501516000610140909101525b60015460608601516040516363029b9f60e11b81526001600160a01b03918216600482015291169063c605373e90602401600060405180830381600087803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b505050505b610160850180514260209182015260008c81526004808352604091829020895181546001600160a01b03199081166001600160a01b03928316178355858c01516001840155848c0151600284015560608c0151600384018054831691841691909117905560808c0151938301805482169483169490941790935560a08b0151600583018054851691831691909117905560c08b0151600683015560e08b015160078301556101008b015160088301556101208b015160098301556101408b0151600a83015594518051600b83018054909416961695909517825584840151600c8201559184015180518a9593946120e792600d8701929101906153c2565b50606082015160038201556080820151805161210d9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050846006600560008d815260200190815260200160002054815481106121d3576121d3615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c8401558301518051929491926122c992600d87019201906153c2565b5060608201516003820155608082015180516122ef9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f90910155505050505050505050505050565b60046020528060005260406000206000915090508060000160009054906101000a90046001600160a01b0316908060010154908060020154908060030160009054906101000a90046001600160a01b0316908060040160009054906101000a90046001600160a01b0316908060050160009054906101000a90046001600160a01b03169080600601549080600701549080600801549080600901549080600a01549080600b01604051806102000160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201805461248d90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546124b990615912565b80156125065780601f106124db57610100808354040283529160200191612506565b820191906000526020600020905b8154815290600101906020018083116124e957829003601f168201915b505050505081526020016003820154815260200160048201805461252990615912565b80601f016020809104026020016040519081016040528092919081815260200182805461255590615912565b80156125a25780601f10612577576101008083540402835291602001916125a2565b820191906000526020600020905b81548152906001019060200180831161258557829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e0820152600c820154610100820152600d820154610120820152600e820154610140820152600f909101546101609091015290508c565b600081815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061270090615912565b80601f016020809104026020016040519081016040528092919081815260200182805461272c90615912565b80156127795780601f1061274e57610100808354040283529160200191612779565b820191906000526020600020905b81548152906001019060200180831161275c57829003601f168201915b505050505081526020016003820154815260200160048201805461279c90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546127c890615912565b80156128155780601f106127ea57610100808354040283529160200191612815565b820191906000526020600020905b8154815290600101906020018083116127f857829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681608001516001600160a01b0316141580156128ea575060a08101516001600160a01b03163314155b6128f357600080fd5b60608101516001600160a01b03161561290b57600080fd5b8060e0015160011461291c57600080fd5b60006129286001614b50565b90508061293457600080fd5b3360608301908152426101208401908152600085815260046020818152604092839020875181546001600160a01b03199081166001600160a01b03928316178355838a01516001840155858a01516002840155965160038301805489169183169190911790556080890151938201805488169482169490941790935560a0880151600582018054881691851691909117905560c0880151600682015560e08801516007820155610100880151600882015593516009850155610140870151600a8501556101608701518051600b86018054909716931692909217855581810151600c85015591810151805187959293612a3492600d8701929101906153c2565b506060820151600382015560808201518051612a5a9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050816006600560008681526020019081526020016000205481548110612b2057612b20615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c840155830151805192949192612c1692600d87019201906153c2565b506060820151600382015560808201518051612c3c9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f909101555050505050565b600081815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d82018054919592946101608701949093929084019190612dac90615912565b80601f0160208091040260200160405190810160405280929190818152602001828054612dd890615912565b8015612e255780601f10612dfa57610100808354040283529160200191612e25565b820191906000526020600020905b815481529060010190602001808311612e0857829003601f168201915b5050505050815260200160038201548152602001600482018054612e4890615912565b80601f0160208091040260200160405190810160405280929190818152602001828054612e7490615912565b8015612ec15780601f10612e9657610100808354040283529160200191612ec1565b820191906000526020600020905b815481529060010190602001808311612ea457829003601f168201915b5050505050815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f82015481525050815250509050336001600160a01b031681608001516001600160a01b031614158015612f96575060a08101516001600160a01b03163314155b612f9f57600080fd5b8060e0015160041480612fb657508060e001516005145b612fbf57600080fd5b61016081015160e001516001600160a01b031615612fdc57600080fd5b6000612fe86002614b50565b905080612ff457600080fd5b610160820180513360e091820152426101408501908152600086815260046020818152604092839020885181546001600160a01b03199081166001600160a01b03928316178355838b01516001840155858b0151600284015560608b0151600384018054831691841691909117905560808b0151948301805482169583169590951790945560a08a0151600583018054861691831691909117905560c08a01516006830155958901516007820155610100890151600882015561012089015160098201559351600a85015594518051600b85018054909316951694909417815583850151600c8401559083015180518795939493612a3492600d8701929101906153c2565b60606006805480602002602001604051908101604052809291908181526020016000905b828210156133aa5760008481526020908190206040805161018081018252601b860290920180546001600160a01b0390811684526001820154848601526002820154848401526003820154811660608501526004820154811660808501526005820154811660a0850152600682015460c0850152600782015460e085015260088201546101008501526009820154610120850152600a820154610140850152825161020081018452600b830180549092168152600c83015495810195909552600d8201805494959294610160870194840191906131f990615912565b80601f016020809104026020016040519081016040528092919081815260200182805461322590615912565b80156132725780601f1061324757610100808354040283529160200191613272565b820191906000526020600020905b81548152906001019060200180831161325557829003601f168201915b505050505081526020016003820154815260200160048201805461329590615912565b80601f01602080910402602001604051908101604052809291908181526020018280546132c190615912565b801561330e5780601f106132e35761010080835404028352916020019161330e565b820191906000526020600020905b8154815290600101906020018083116132f157829003601f168201915b505050918352505060058201546020808301919091526006830154604083015260078301546001600160a01b0316606083015260088301546080830152600983015460a0830152600a83015460c0830152600b83015460e0830152600c830154610100830152600d830154610120830152600e830154610140830152600f9092015461016090910152915291835250600192909201910161311d565b50505050905090565b600080546040516362bb335f60e11b8152600481018490528392916001600160a01b03169063c57666be906024016000604051808303816000875af1158015613400573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134289190810190615af5565b610120810151602001519091506001600160a01b03163314806134595750610120810151516001600160a01b031633145b61346257600080fd5b600154604080516358e5ed9b60e01b815290516000926001600160a01b0316916358e5ed9b9160048083019260209291908290030181865afa1580156134ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134d0919061594d565b90506134dc8482614be5565b600154604051630bc67f9b60e01b815260206004820152600560248201526477524f534560d81b60448201526000916001600160a01b031690630bc67f9b906064016020604051808303816000875af115801561353d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135619190615be4565b6003546040516323b872dd60e01b81523360048201526001600160a01b039182166024820152604481018590529192508216906323b872dd90606401600060405180830381600087803b1580156135b757600080fd5b505af11580156135cb573d6000803e3d6000fd5b505050505050505050565b600681815481106135e657600080fd5b90600052602060002090601b02016000915090508060000160009054906101000a90046001600160a01b0316908060010154908060020154908060030160009054906101000a90046001600160a01b0316908060040160009054906101000a90046001600160a01b0316908060050160009054906101000a90046001600160a01b03169080600601549080600701549080600801549080600901549080600a01549080600b01604051806102000160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201805461248d90615912565b600080546040516362bb335f60e11b8152600481018490528392916001600160a01b03169063c57666be906024016000604051808303816000875af115801561372e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137569190810190615af5565b610120810151602001519091506001600160a01b03163314806137875750610120810151516001600160a01b031633145b61379057600080fd5b600083815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061386490615912565b80601f016020809104026020016040519081016040528092919081815260200182805461389090615912565b80156138dd5780601f106138b2576101008083540402835291602001916138dd565b820191906000526020600020905b8154815290600101906020018083116138c057829003601f168201915b505050505081526020016003820154815260200160048201805461390090615912565b80601f016020809104026020016040519081016040528092919081815260200182805461392c90615912565b80156139795780601f1061394e57610100808354040283529160200191613979565b820191906000526020600020905b81548152906001019060200180831161395c57829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e080830191909152600c830154610100830152600d830154610120830152600e830154610140830152600f909201546101609091015291528201519192505060021480613a1d57508060e001516003145b613a2657600080fd5b6201518081610160015160a0015142613a3f9190615c17565b1115613a4a57600080fd5b613a608160a0015182608001516001600061473d565b60015460408051632c96c35760e11b815290516000926001600160a01b03169163592d86ae9160048083019260209291908290030181865afa158015613aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ace919061594d565b600154604051630bc67f9b60e01b815260206004820152600560248201526477524f534560d81b60448201529192506000916001600160a01b0390911690630bc67f9b906064016020604051808303816000875af1158015613b34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b589190615be4565b6003546040516323b872dd60e01b81523360048201526001600160a01b039182166024820152604481018590529192508216906323b872dd90606401600060405180830381600087803b158015613bae57600080fd5b505af1158015613bc2573d6000803e3d6000fd5b505050508260e0015160021415613bdf57600460e0840152613bf4565b8260e0015160031415613bf457600560e08401525b6101608301805133905280514260209182015260008881526004808352604091829020875181546001600160a01b03199081166001600160a01b03928316178355858a01516001840155848a0151600284015560608a0151600384018054831691841691909117905560808a0151938301805482169483169490941790935560a0890151600583018054851691831691909117905560c0890151600683015560e0890151600783015561010089015160088301556101208901516009830155610140890151600a83015594518051600b83018054909416961695909517825584840151600c82015591840151805188959394613cf792600d8701929101906153c2565b506060820151600382015560808201518051613d1d9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f01555050905050826006600560008981526020019081526020016000205481548110613de357613de3615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c840155830151805192949192613ed992600d87019201906153c2565b506060820151600382015560808201518051613eff9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f909101555050505050505050565b600080546040516362bb335f60e11b8152600481018590528492916001600160a01b03169063c57666be906024016000604051808303816000875af1158015613feb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526140139190810190615af5565b610120810151602001519091506001600160a01b03163314806140445750610120810151516001600160a01b031633145b61404d57600080fd5b600084815260046020818152604080842081516101808101835281546001600160a01b03908116825260018301548286015260028301548285015260038301548116606083015294820154851660808201526005820154851660a0820152600682015460c0820152600782015460e082015260088201546101008201526009820154610120820152600a820154610140820152825161020081018452600b830180549096168152600c83015494810194909452600d8201805491959294610160870194909392908401919061412190615912565b80601f016020809104026020016040519081016040528092919081815260200182805461414d90615912565b801561419a5780601f1061416f5761010080835404028352916020019161419a565b820191906000526020600020905b81548152906001019060200180831161417d57829003601f168201915b50505050508152602001600382015481526020016004820180546141bd90615912565b80601f01602080910402602001604051908101604052809291908181526020018280546141e990615912565b80156142365780601f1061420b57610100808354040283529160200191614236565b820191906000526020600020905b81548152906001019060200180831161421957829003601f168201915b5050509183525050600582015460208201526006820154604082015260078201546001600160a01b0316606082015260088201546080820152600982015460a0820152600a82015460c0820152600b82015460e0820152600c820154610100820152600d820154610120820152600e820154610140820152600f909101546101609091015290525090506001841415614324578060e001516001146142da57600080fd5b60608101516001600160a01b03166142f157600080fd5b62015180816101200151426143069190615c17565b1161431057600080fd5b60006060820181905261012082015261439f565b836002141561439f578060e001516004148061434457508060e001516005145b61434d57600080fd5b61016081015160e001516001600160a01b031661436957600080fd5b620151808161014001514261437e9190615c17565b1161438857600080fd5b610160810151600060e09091018190526101408201525b600085815260046020818152604092839020845181546001600160a01b03199081166001600160a01b03928316178355868401516001840155868601516002840155606087015160038401805483169184169190911790556080870151948301805482169583169590951790945560a0860151600583018054861691831691909117905560c0860151600683015560e0860151600783015561010086015160088301556101208601516009830155610140860151600a8301556101608601518051600b84018054909616921691909117845580830151600c83015593840151805186959294929361449792600d8701929101906153c2565b5060608201516003820155608082015180516144bd9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0155505090505080600660056000888152602001908152602001600020548154811061458357614583615966565b60009182526020918290208351601b929092020180546001600160a01b03199081166001600160a01b039384161782558484015160018301556040808601516002840155606086015160038401805484169186169190911790556080860151600484018054841691861691909117905560a0860151600584018054841691861691909117905560c0860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a8401556101608601518051600b85018054909416951694909417825583850151600c84015583015180519294919261467992600d87019201906153c2565b50606082015160038201556080820151805161469f9160048401916020909101906153c2565b5060a0820151600582015560c0820151600682015560e08201516007820180546001600160a01b0319166001600160a01b0390921691909117905561010082015160088201556101208201516009820155610140820151600a820155610160820151600b820155610180820151600c8201556101a0820151600d8201556101c0820151600e8201556101e090910151600f9091015550505050505050565b60015460408051635c7cee6360e01b815290516000926001600160a01b031691635c7cee639160048083019260209291908290030181865afa158015614787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147ab919061594d565b90506000600160009054906101000a90046001600160a01b03166001600160a01b031663c941455c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614802573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614826919061594d565b600254604051639bd7417f60e01b81526001600160a01b03898116600483015292935060009290911690639bd7417f90602401600060405180830381865afa158015614876573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261489e9190810190615d01565b60e0810151600254604051639bd7417f60e01b81526001600160a01b038a811660048301529394509192600092911690639bd7417f90602401600060405180830381865afa1580156148f4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261491c9190810190615d01565b60e081015160a08083015190860151929350909160018a14156149ae578451614946576000614954565b845161495490600190615c17565b85528251614963576000614971565b825161497190600190615c17565b83528781101561498257600061498c565b61498c8882615c17565b90508782101561499d5760006149a7565b6149a78883615c17565b9150614a41565b8960021415614a41576001856000018181516149ca9190615df2565b905250825160019084906149df908390615df2565b9052506001891415614a10576149f58882615df2565b905086821015614a065760006149a7565b6149a78783615c17565b8860021415614a4157614a238883615df2565b915086811015614a34576000614a3e565b614a3e8782615c17565b90505b6002546040516316a1e96960e31b81526001600160a01b038e811660048301528751602483015260208801516044830152606482018490529091169063b50f4b4890608401600060405180830381600087803b158015614aa057600080fd5b505af1158015614ab4573d6000803e3d6000fd5b50506002546040516316a1e96960e31b81526001600160a01b038f81166004830152875160248301526020880151604483015260648201879052909116925063b50f4b489150608401600060405180830381600087803b158015614b1757600080fd5b505af1158015614b2b573d6000803e3d6000fd5b50505050505050505050505050505050565b6000614b498284615c17565b9392505050565b600254604051639bd7417f60e01b815233600482015260009182916001600160a01b0390911690639bd7417f90602401600060405180830381865afa158015614b9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614bc59190810190615d01565b90508281608001511415614bdc5750600192915050565b50600092915050565b600080546040516362bb335f60e11b8152600481018590526001600160a01b039091169063c57666be906024016000604051808303816000875af1158015614c31573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614c599190810190615af5565b60008481526004602052604090206001015490915015614c7857600080fd5b600060405180610200016040528060006001600160a01b031681526020016000815260200160405180602001604052806000815250815260200160008152602001604051806020016040528060008152508152602001600081526020016000815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815250905060004290506000604051806101800160405280336001600160a01b0316815260200183815260200187815260200160006001600160a01b03168152602001856101200151600001516001600160a01b03168152602001856101200151602001516001600160a01b03168152602001868152602001600181526020014281526020016000815260200160008152602001848152509050806004600088815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002019080519060200190614f279291906153c2565b506060820151600382015560808201518051614f4d9160048401916020909101906153c2565b5060a0820151816005015560c0820151816006015560e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0155505090505060068190806001815401808255809150506001900390600052602060002090601b020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015560608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020190805190602001906151729291906153c2565b5060608201516003820155608082015180516151989160048401916020909101906153c2565b5060a0820151600582015560c082015160068083019190915560e08301516007830180546001600160a01b0319166001600160a01b0390921691909117905561010083015160088301556101208301516009830155610140830151600a830155610160830151600b830155610180830151600c8301556101a0830151600d8301556101c0830151600e8301556101e090920151600f9091015554615240925060019150615c17565b600087815260056020908152604082209290925561012086015191820151915161526d929160019061473d565b60408051838152602081018890527f6b787c191423cbfdb42197fdc3357a6627229f66a0bccccba5d1841388364604910160405180910390a1505050505050565b60405180610180016040528060006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016153bd60405180610200016040528060006001600160a01b0316815260200160008152602001606081526020016000815260200160608152602001600081526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b905290565b8280546153ce90615912565b90600052602060002090601f0160209004810192826153f05760008555615436565b82601f1061540957805160ff1916838001178555615436565b82800160010185558215615436579182015b8281111561543657825182559160200191906001019061541b565b50615442929150615446565b5090565b5b808211156154425760008155600101615447565b60006020828403121561546d57600080fd5b5035919050565b60005b8381101561548f578181015183820152602001615477565b8381111561549e576000848401525b50505050565b600081518084526154bc816020860160208601615474565b601f01601f19169290920160200192915050565b80516001600160a01b031682526000610200602083015160208501526040830151816040860152615503828601826154a4565b915050606083015160608501526080830151848203608086015261552782826154a4565b91505060a083015160a085015260c083015160c085015260e083015161555860e08601826001600160a01b03169052565b50610100838101519085015261012080840151908501526101408084015190850152610160808401519085015261018080840151908501526101a080840151908501526101c080840151908501526101e09283015192909301919091525090565b80516001600160a01b031682526000610180602083015160208501526040830151604085015260608301516155f960608601826001600160a01b03169052565b50608083015161561460808601826001600160a01b03169052565b5060a083015161562f60a08601826001600160a01b03169052565b5060c083015160c085015260e083015160e0850152610100808401518186015250610120808401518186015250610140808401518186015250610160808401518282870152615680838701826154d0565b9695505050505050565b602081526000614b4960208301846155b9565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156156d7576156d761569d565b60405290565b604051610140810167ffffffffffffffff811182821017156156d7576156d761569d565b604051610120810167ffffffffffffffff811182821017156156d7576156d761569d565b604051601f8201601f1916810167ffffffffffffffff8111828210171561574e5761574e61569d565b604052919050565b600067ffffffffffffffff8211156157705761577061569d565b50601f01601f191660200190565b60008060006060848603121561579357600080fd5b83359250602084013567ffffffffffffffff8111156157b157600080fd5b8401601f810186136157c257600080fd5b80356157d56157d082615756565b615725565b8181528760208385010111156157ea57600080fd5b81602084016020830137600060208383010152809450505050604084013590509250925092565b600060018060a01b03808f1683528d60208401528c6040840152808c166060840152808b166080840152808a1660a0840152508760c08301528660e083015285610100830152846101208301528361014083015261018061016083015261587c6101808301846154d0565b9e9d5050505050505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156158e357603f198886030184526158d18583516155b9565b945092850192908501906001016158b5565b5092979650505050505050565b6000806040838503121561590357600080fd5b50508035926020909101359150565b600181811c9082168061592657607f821691505b6020821081141561594757634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561595f57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0387811682528616602082015260c0604082018190526000906159a8908301876155b9565b606083019590955250608081019290925260a0909101529392505050565b6001600160a01b03811681146159db57600080fd5b50565b80516159e9816159c6565b919050565b600082601f8301126159ff57600080fd5b8151615a0d6157d082615756565b818152846020838601011115615a2257600080fd5b615a33826020830160208701615474565b949350505050565b60006101008284031215615a4e57600080fd5b615a566156b3565b9050615a61826159de565b8152615a6f602083016159de565b6020820152604082015167ffffffffffffffff80821115615a8f57600080fd5b615a9b858386016159ee565b6040840152606084015160608401526080840151608084015260a084015160a084015260c0840151915080821115615ad257600080fd5b50615adf848285016159ee565b60c08301525060e082015160e082015292915050565b600060208284031215615b0757600080fd5b815167ffffffffffffffff80821115615b1f57600080fd5b908301906101408286031215615b3457600080fd5b615b3c6156dd565b615b45836159de565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015182811115615b8b57600080fd5b615b97878286016159ee565b60c08301525060e083015160e08201526101008084015181830152506101208084015183811115615bc757600080fd5b615bd388828701615a3b565b918301919091525095945050505050565b600060208284031215615bf657600080fd5b8151614b49816159c6565b634e487b7160e01b600052601160045260246000fd5b600082821015615c2957615c29615c01565b500390565b600060408284031215615c4057600080fd5b6040516040810181811067ffffffffffffffff82111715615c6357615c6361569d565b604052825181526020928301519281019290925250919050565b600060e08284031215615c8f57600080fd5b60405160e0810181811067ffffffffffffffff82111715615cb257615cb261569d565b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201525092915050565b600060208284031215615d1357600080fd5b815167ffffffffffffffff80821115615d2b57600080fd5b908301906102008286031215615d4057600080fd5b615d48615701565b615d51836159de565b8152602083015182811115615d6557600080fd5b615d71878286016159ee565b602083015250604083015182811115615d8957600080fd5b615d95878286016159ee565b604083015250606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152615dd08660e08501615c2e565b60e0820152615de3866101208501615c7d565b61010082015295945050505050565b60008219821115615e0557615e05615c01565b50019056fea26469706673582212204cccb338c05fa54f4a8da06be187a39fb14fbe533f0d3d60d86ff80f4f3ba7ff64736f6c634300080b0033