Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MorpherTradeEngine
Compiler Version
v0.5.16+commit.9c3226ce
Contract Source Code (Solidity Multiple files format)
pragma solidity 0.5.16;
import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";
import "./IMorpherStaking.sol";
import "./MorpherMintingLimiter.sol";
// ----------------------------------------------------------------------------------
// Tradeengine of the Morpher platform
// Creates and processes orders, and computes the state change of portfolio.
// Needs writing/reading access to/from Morpher State. Order objects are stored locally,
// portfolios are stored in state.
// ----------------------------------------------------------------------------------
contract MorpherTradeEngine is Ownable {
MorpherState state;
IMorpherStaking staking;
MorpherMintingLimiter mintingLimiter;
using SafeMath for uint256;
// ----------------------------------------------------------------------------
// Precision of prices and leverage
// ----------------------------------------------------------------------------
uint256 constant PRECISION = 10**8;
uint256 public orderNonce;
bytes32 public lastOrderId;
uint256 public deployedTimeStamp;
address public escrowOpenOrderAddress = 0x1111111111111111111111111111111111111111;
bool public escrowOpenOrderEnabled;
//we're locking positions in for this price at a market marketId;
address public closedMarketPriceLock = 0x0000000000000000000000000000000000000001;
// ----------------------------------------------------------------------------
// Order struct contains all order specific varibles. Variables are completed
// during processing of trade. State changes are saved in the order struct as
// well, since local variables would lead to stack to deep errors *sigh*.
// ----------------------------------------------------------------------------
struct order {
address userId;
bytes32 marketId;
uint256 closeSharesAmount;
uint256 openMPHTokenAmount;
bool tradeDirection; // true = long, false = short
uint256 liquidationTimestamp;
uint256 marketPrice;
uint256 marketSpread;
uint256 orderLeverage;
uint256 timeStamp;
uint256 longSharesOrder;
uint256 shortSharesOrder;
uint256 balanceDown;
uint256 balanceUp;
uint256 newLongShares;
uint256 newShortShares;
uint256 newMeanEntryPrice;
uint256 newMeanEntrySpread;
uint256 newMeanEntryLeverage;
uint256 newLiquidationPrice;
uint256 orderEscrowAmount;
}
mapping(bytes32 => order) private orders;
// ----------------------------------------------------------------------------
// Events
// Order created/processed events are fired by MorpherOracle.
// ----------------------------------------------------------------------------
event PositionLiquidated(
address indexed _address,
bytes32 indexed _marketId,
bool _longPosition,
uint256 _timeStamp,
uint256 _marketPrice,
uint256 _marketSpread
);
event OrderCancelled(
bytes32 indexed _orderId,
address indexed _address
);
event OrderIdRequested(
bytes32 _orderId,
address indexed _address,
bytes32 indexed _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
bool _tradeDirection,
uint256 _orderLeverage
);
event OrderProcessed(
bytes32 _orderId,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _liquidationTimestamp,
uint256 _timeStamp,
uint256 _newLongShares,
uint256 _newShortShares,
uint256 _newAverageEntry,
uint256 _newAverageSpread,
uint256 _newAverageLeverage,
uint256 _liquidationPrice
);
event PositionUpdated(
address _userId,
bytes32 _marketId,
uint256 _timeStamp,
uint256 _newLongShares,
uint256 _newShortShares,
uint256 _newMeanEntryPrice,
uint256 _newMeanEntrySpread,
uint256 _newMeanEntryLeverage,
uint256 _newLiquidationPrice,
uint256 _mint,
uint256 _burn
);
event LinkState(address _address);
event LinkStaking(address _stakingAddress);
event LinkMintingLimiter(address _mintingLimiterAddress);
event LockedPriceForClosingPositions(bytes32 _marketId, uint256 _price);
constructor(address _stateAddress, address _coldStorageOwnerAddress, address _stakingContractAddress, bool _escrowOpenOrderEnabled, uint256 _deployedTimestampOverride, address _mintingLimiterAddress) public {
setMorpherState(_stateAddress);
setMorpherStaking(_stakingContractAddress);
setMorpherMintingLimiter(_mintingLimiterAddress);
transferOwnership(_coldStorageOwnerAddress);
escrowOpenOrderEnabled = _escrowOpenOrderEnabled;
deployedTimeStamp = _deployedTimestampOverride > 0 ? _deployedTimestampOverride : block.timestamp;
}
modifier onlyOracle {
require(msg.sender == state.getOracleContract(), "MorpherTradeEngine: function can only be called by Oracle Contract.");
_;
}
modifier onlyAdministrator {
require(msg.sender == getAdministrator(), "MorpherTradeEngine: function can only be called by the Administrator.");
_;
}
// ----------------------------------------------------------------------------
// Administrative functions
// Set state address, get administrator address
// ----------------------------------------------------------------------------
function setMorpherState(address _stateAddress) public onlyOwner {
state = MorpherState(_stateAddress);
emit LinkState(_stateAddress);
}
function setMorpherStaking(address _stakingAddress) public onlyOwner {
staking = IMorpherStaking(_stakingAddress);
emit LinkStaking(_stakingAddress);
}
function setMorpherMintingLimiter(address _mintingLimiterAddress) public onlyOwner {
mintingLimiter = MorpherMintingLimiter(_mintingLimiterAddress);
emit LinkMintingLimiter(_mintingLimiterAddress);
}
function getAdministrator() public view returns(address _administrator) {
return state.getAdministrator();
}
function setEscrowOpenOrderEnabled(bool _isEnabled) public onlyOwner {
escrowOpenOrderEnabled = _isEnabled;
}
function paybackEscrow(bytes32 _orderId) private {
//pay back the escrow to the user so he has it back on his balance/**
if(orders[_orderId].orderEscrowAmount > 0) {
//checks effects interaction
uint256 paybackAmount = orders[_orderId].orderEscrowAmount;
orders[_orderId].orderEscrowAmount = 0;
state.transfer(escrowOpenOrderAddress, orders[_orderId].userId, paybackAmount);
}
}
function buildupEscrow(bytes32 _orderId, uint256 _amountInMPH) private {
if(escrowOpenOrderEnabled && _amountInMPH > 0) {
state.transfer(orders[_orderId].userId, escrowOpenOrderAddress, _amountInMPH);
orders[_orderId].orderEscrowAmount = _amountInMPH;
}
}
function validateClosedMarketOrderConditions(address _address, bytes32 _marketId, uint256 _closeSharesAmount, uint256 _openMPHTokenAmount, bool _tradeDirection ) internal view {
//markets active? Still tradeable?
if(_openMPHTokenAmount > 0) {
require(state.getMarketActive(_marketId) == true, "MorpherTradeEngine: market unknown or currently not enabled for trading.");
} else {
//we're just closing a position, but it needs a forever price locked in if market is not active
//the user needs to close his complete position
if(state.getMarketActive(_marketId) == false) {
require(getDeactivatedMarketPrice(_marketId) > 0, "MorpherTradeEngine: Can't close a position, market not active and closing price not locked");
if(_tradeDirection) {
//long
require(_closeSharesAmount == state.getShortShares(_address, _marketId), "MorpherTradeEngine: Deactivated market order needs all shares to be closed");
} else {
//short
require(_closeSharesAmount == state.getLongShares(_address, _marketId), "MorpherTradeEngine: Deactivated market order needs all shares to be closed");
}
}
}
}
//wrapper for stack too deep errors
function validateClosedMarketOrder(bytes32 _orderId) internal view {
validateClosedMarketOrderConditions(orders[_orderId].userId, orders[_orderId].marketId, orders[_orderId].closeSharesAmount, orders[_orderId].openMPHTokenAmount, orders[_orderId].tradeDirection);
}
// ----------------------------------------------------------------------------
// requestOrderId(address _address, bytes32 _marketId, bool _closeSharesAmount, uint256 _openMPHTokenAmount, bool _tradeDirection, uint256 _orderLeverage)
// Creates a new order object with unique orderId and assigns order information.
// Must be called by MorpherOracle contract.
// ----------------------------------------------------------------------------
function requestOrderId(
address _address,
bytes32 _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
bool _tradeDirection,
uint256 _orderLeverage
) public onlyOracle returns (bytes32 _orderId) {
require(_orderLeverage >= PRECISION, "MorpherTradeEngine: leverage too small. Leverage precision is 1e8");
require(_orderLeverage <= state.getMaximumLeverage(), "MorpherTradeEngine: leverage exceeds maximum allowed leverage.");
validateClosedMarketOrderConditions(_address, _marketId, _closeSharesAmount, _openMPHTokenAmount, _tradeDirection);
//request limits
require(state.getNumberOfRequests(_address) <= state.getNumberOfRequestsLimit() ||
state.getLastRequestBlock(_address) < block.number,
"MorpherTradeEngine: request exceeded maximum permitted requests per block."
);
/**
* The user can't partially close a position and open another one with MPH
*/
if(_openMPHTokenAmount > 0) {
if(_tradeDirection) {
//long
require(_closeSharesAmount == state.getShortShares(_address, _marketId), "MorpherTradeEngine: Can't partially close a position and open another one in opposite direction");
} else {
//short
require(_closeSharesAmount == state.getLongShares(_address, _marketId), "MorpherTradeEngine: Can't partially close a position and open another one in opposite direction");
}
}
state.setLastRequestBlock(_address);
state.increaseNumberOfRequests(_address);
orderNonce++;
_orderId = keccak256(
abi.encodePacked(
_address,
block.number,
_marketId,
_closeSharesAmount,
_openMPHTokenAmount,
_tradeDirection,
_orderLeverage,
orderNonce
)
);
lastOrderId = _orderId;
orders[_orderId].userId = _address;
orders[_orderId].marketId = _marketId;
orders[_orderId].closeSharesAmount = _closeSharesAmount;
orders[_orderId].openMPHTokenAmount = _openMPHTokenAmount;
orders[_orderId].tradeDirection = _tradeDirection;
orders[_orderId].orderLeverage = _orderLeverage;
emit OrderIdRequested(
_orderId,
_address,
_marketId,
_closeSharesAmount,
_openMPHTokenAmount,
_tradeDirection,
_orderLeverage
);
/**
* put the money in escrow here if given MPH to open an order
* - also, can only close positions if in shares, so it will
* definitely trigger a mint there.
* The money must be put in escrow even though we have an existing position
*/
buildupEscrow(_orderId, _openMPHTokenAmount);
return _orderId;
}
// ----------------------------------------------------------------------------
// Getter functions for orders, shares, and positions
// ----------------------------------------------------------------------------
function getOrder(bytes32 _orderId) public view returns (
address _userId,
bytes32 _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _orderLeverage
) {
return(
orders[_orderId].userId,
orders[_orderId].marketId,
orders[_orderId].closeSharesAmount,
orders[_orderId].openMPHTokenAmount,
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
orders[_orderId].orderLeverage
);
}
function getPosition(address _address, bytes32 _marketId) public view returns (
uint256 _positionLongShares,
uint256 _positionShortShares,
uint256 _positionAveragePrice,
uint256 _positionAverageSpread,
uint256 _positionAverageLeverage,
uint256 _liquidationPrice
) {
return(
state.getLongShares(_address, _marketId),
state.getShortShares(_address, _marketId),
state.getMeanEntryPrice(_address,_marketId),
state.getMeanEntrySpread(_address,_marketId),
state.getMeanEntryLeverage(_address,_marketId),
state.getLiquidationPrice(_address,_marketId)
);
}
function setDeactivatedMarketPrice(bytes32 _marketId, uint256 _price) public onlyOracle {
state.setPosition(
closedMarketPriceLock,
_marketId,
now.mul(1000),
0,
0,
_price,
0,
0,
0
);
emit LockedPriceForClosingPositions(_marketId, _price);
}
function getDeactivatedMarketPrice(bytes32 _marketId) public view returns(uint256) {
( , , uint positionForeverClosingPrice, , ,) = state.getPosition(closedMarketPriceLock, _marketId);
return positionForeverClosingPrice;
}
// ----------------------------------------------------------------------------
// liquidate(bytes32 _orderId)
// Checks for bankruptcy of position between its last update and now
// Time check is necessary to avoid two consecutive / unorderded liquidations
// ----------------------------------------------------------------------------
function liquidate(bytes32 _orderId) private {
address _address = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
uint256 _liquidationTimestamp = orders[_orderId].liquidationTimestamp;
if (_liquidationTimestamp > state.getLastUpdated(_address, _marketId)) {
if (state.getLongShares(_address,_marketId) > 0) {
state.setPosition(
_address,
_marketId,
orders[_orderId].timeStamp,
0,
state.getShortShares(_address, _marketId),
0,
0,
PRECISION,
0);
emit PositionLiquidated(
_address,
_marketId,
true,
orders[_orderId].timeStamp,
orders[_orderId].marketPrice,
orders[_orderId].marketSpread
);
}
if (state.getShortShares(_address,_marketId) > 0) {
state.setPosition(
_address,
_marketId,
orders[_orderId].timeStamp,
state.getLongShares(_address, _marketId),
0,
0,
0,
PRECISION,
0
);
emit PositionLiquidated(
_address,
_marketId,
false,
orders[_orderId].timeStamp,
orders[_orderId].marketPrice,
orders[_orderId].marketSpread
);
}
}
}
// ----------------------------------------------------------------------------
// processOrder(bytes32 _orderId, uint256 _marketPrice, uint256 _marketSpread, uint256 _liquidationTimestamp, uint256 _timeStamp)
// ProcessOrder receives the price/spread/liqidation information from the Oracle and
// triggers the processing of the order. If successful, processOrder updates the portfolio state.
// Liquidation time check is necessary to avoid two consecutive / unorderded liquidations
// ----------------------------------------------------------------------------
function processOrder(
bytes32 _orderId,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _liquidationTimestamp,
uint256 _timeStampInMS
) public onlyOracle returns (
uint256 _newLongShares,
uint256 _newShortShares,
uint256 _newAverageEntry,
uint256 _newAverageSpread,
uint256 _newAverageLeverage,
uint256 _liquidationPrice
) {
require(orders[_orderId].userId != address(0), "MorpherTradeEngine: unable to process, order has been deleted.");
require(_marketPrice > 0, "MorpherTradeEngine: market priced at zero. Buy order cannot be processed.");
require(_marketPrice >= _marketSpread, "MorpherTradeEngine: market price lower then market spread. Order cannot be processed.");
orders[_orderId].marketPrice = _marketPrice;
orders[_orderId].marketSpread = _marketSpread;
orders[_orderId].timeStamp = _timeStampInMS;
orders[_orderId].liquidationTimestamp = _liquidationTimestamp;
/**
* If the market is deactivated, then override the price with the locked in market price
* if the price wasn't locked in: error out.
*/
if(state.getMarketActive(orders[_orderId].marketId) == false) {
validateClosedMarketOrder(_orderId);
orders[_orderId].marketPrice = getDeactivatedMarketPrice(orders[_orderId].marketId);
}
// Check if previous position on that market was liquidated
if (_liquidationTimestamp > state.getLastUpdated(orders[_orderId].userId, orders[_orderId].marketId)) {
liquidate(_orderId);
}
paybackEscrow(_orderId);
if (orders[_orderId].tradeDirection) {
processBuyOrder(_orderId);
} else {
processSellOrder(_orderId);
}
address _address = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
delete orders[_orderId];
emit OrderProcessed(
_orderId,
_marketPrice,
_marketSpread,
_liquidationTimestamp,
_timeStampInMS,
_newLongShares,
_newShortShares,
_newAverageEntry,
_newAverageSpread,
_newAverageLeverage,
_liquidationPrice
);
return (
state.getLongShares(_address, _marketId),
state.getShortShares(_address, _marketId),
state.getMeanEntryPrice(_address,_marketId),
state.getMeanEntrySpread(_address,_marketId),
state.getMeanEntryLeverage(_address,_marketId),
state.getLiquidationPrice(_address,_marketId)
);
}
// ----------------------------------------------------------------------------
// function cancelOrder(bytes32 _orderId, address _address)
// Users or Administrator can delete pending orders before the callback went through
// ----------------------------------------------------------------------------
function cancelOrder(bytes32 _orderId, address _address) public onlyOracle {
require(_address == orders[_orderId].userId || _address == getAdministrator(), "MorpherTradeEngine: only Administrator or user can cancel an order.");
require(orders[_orderId].userId != address(0), "MorpherTradeEngine: unable to process, order does not exist.");
/**
* Pay back any escrow there
*/
paybackEscrow(_orderId);
delete orders[_orderId];
emit OrderCancelled(_orderId, _address);
}
// ----------------------------------------------------------------------------
// shortShareValue / longShareValue compute the value of a virtual future
// given current price/spread/leverage of the market and mean price/spread/leverage
// at the beginning of the trade
// ----------------------------------------------------------------------------
function shortShareValue(
uint256 _positionAveragePrice,
uint256 _positionAverageLeverage,
uint256 _positionTimeStampInMs,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _orderLeverage,
bool _sell
) public view returns (uint256 _shareValue) {
uint256 _averagePrice = _positionAveragePrice;
uint256 _averageLeverage = _positionAverageLeverage;
if (_positionAverageLeverage < PRECISION) {
// Leverage can never be less than 1. Fail safe for empty positions, i.e. undefined _positionAverageLeverage
_averageLeverage = PRECISION;
}
if (_sell == false) {
// New short position
// It costs marketPrice + marketSpread to build up a new short position
_averagePrice = _marketPrice;
// This is the average Leverage
_averageLeverage = _orderLeverage;
}
if (
getLiquidationPrice(_averagePrice, _averageLeverage, false, _positionTimeStampInMs) <= _marketPrice
) {
// Position is worthless
_shareValue = 0;
} else {
// The regular share value is 2x the entry price minus the current price for short positions.
_shareValue = _averagePrice.mul((PRECISION.add(_averageLeverage))).div(PRECISION);
_shareValue = _shareValue.sub(_marketPrice.mul(_averageLeverage).div(PRECISION));
if (_sell == true) {
// We have to reduce the share value by the average spread (i.e. the average expense to build up the position)
// and reduce the value further by the spread for selling.
_shareValue = _shareValue.sub(_marketSpread.mul(_averageLeverage).div(PRECISION));
uint256 _marginInterest = calculateMarginInterest(_averagePrice, _averageLeverage, _positionTimeStampInMs);
if (_marginInterest <= _shareValue) {
_shareValue = _shareValue.sub(_marginInterest);
} else {
_shareValue = 0;
}
} else {
// If a new short position is built up each share costs value + spread
_shareValue = _shareValue.add(_marketSpread.mul(_orderLeverage).div(PRECISION));
}
}
return _shareValue;
}
function longShareValue(
uint256 _positionAveragePrice,
uint256 _positionAverageLeverage,
uint256 _positionTimeStampInMs,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _orderLeverage,
bool _sell
) public view returns (uint256 _shareValue) {
uint256 _averagePrice = _positionAveragePrice;
uint256 _averageLeverage = _positionAverageLeverage;
if (_positionAverageLeverage < PRECISION) {
// Leverage can never be less than 1. Fail safe for empty positions, i.e. undefined _positionAverageLeverage
_averageLeverage = PRECISION;
}
if (_sell == false) {
// New long position
// It costs marketPrice + marketSpread to build up a new long position
_averagePrice = _marketPrice;
// This is the average Leverage
_averageLeverage = _orderLeverage;
}
if (
_marketPrice <= getLiquidationPrice(_averagePrice, _averageLeverage, true, _positionTimeStampInMs)
) {
// Position is worthless
_shareValue = 0;
} else {
_shareValue = _averagePrice.mul(_averageLeverage.sub(PRECISION)).div(PRECISION);
// The regular share value is market price times leverage minus entry price times entry leverage minus one.
_shareValue = (_marketPrice.mul(_averageLeverage).div(PRECISION)).sub(_shareValue);
if (_sell == true) {
// We sell a long and have to correct the shareValue with the averageSpread and the currentSpread for selling.
_shareValue = _shareValue.sub(_marketSpread.mul(_averageLeverage).div(PRECISION));
uint256 _marginInterest = calculateMarginInterest(_averagePrice, _averageLeverage, _positionTimeStampInMs);
if (_marginInterest <= _shareValue) {
_shareValue = _shareValue.sub(_marginInterest);
} else {
_shareValue = 0;
}
} else {
// We buy a new long position and have to pay the spread
_shareValue = _shareValue.add(_marketSpread.mul(_orderLeverage).div(PRECISION));
}
}
return _shareValue;
}
// ----------------------------------------------------------------------------
// calculateMarginInterest(uint256 _averagePrice, uint256 _averageLeverage, uint256 _positionTimeStamp)
// Calculates the interest for leveraged positions
// ----------------------------------------------------------------------------
function calculateMarginInterest(uint256 _averagePrice, uint256 _averageLeverage, uint256 _positionTimeStampInMs) public view returns (uint256 _marginInterest) {
if (_positionTimeStampInMs.div(1000) < deployedTimeStamp) {
_positionTimeStampInMs = deployedTimeStamp.mul(1000);
}
_marginInterest = _averagePrice.mul(_averageLeverage.sub(PRECISION));
_marginInterest = _marginInterest.mul((now.sub(_positionTimeStampInMs.div(1000)).div(86400)).add(1));
_marginInterest = _marginInterest.mul(staking.interestRate()).div(PRECISION).div(PRECISION);
return _marginInterest;
}
// ----------------------------------------------------------------------------
// processBuyOrder(bytes32 _orderId)
// Converts orders specified in virtual shares to orders specified in Morpher token
// and computes the number of short shares that are sold and long shares that are bought.
// long shares are bought only if the order amount exceeds all open short positions
// ----------------------------------------------------------------------------
function processBuyOrder(bytes32 _orderId) private {
if (orders[_orderId].closeSharesAmount > 0) {
//calcualte the balanceUp/down first
//then reopen the position with MPH amount
// Investment was specified in shares
if (orders[_orderId].closeSharesAmount <= state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId)) {
// Partial closing of short position
orders[_orderId].shortSharesOrder = orders[_orderId].closeSharesAmount;
} else {
// Closing of entire short position
orders[_orderId].shortSharesOrder = state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId);
}
}
//calculate the long shares, but only if the old position is completely closed out (if none exist shortSharesOrder = 0)
if(
orders[_orderId].shortSharesOrder == state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId) &&
orders[_orderId].openMPHTokenAmount > 0
) {
orders[_orderId].longSharesOrder = orders[_orderId].openMPHTokenAmount.div(
longShareValue(
orders[_orderId].marketPrice,
orders[_orderId].orderLeverage,
now,
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
orders[_orderId].orderLeverage,
false
));
}
// Investment equals number of shares now.
if (orders[_orderId].shortSharesOrder > 0) {
closeShort(_orderId);
}
if (orders[_orderId].longSharesOrder > 0) {
openLong(_orderId);
}
}
// ----------------------------------------------------------------------------
// processSellOrder(bytes32 _orderId)
// Converts orders specified in virtual shares to orders specified in Morpher token
// and computes the number of long shares that are sold and short shares that are bought.
// short shares are bought only if the order amount exceeds all open long positions
// ----------------------------------------------------------------------------
function processSellOrder(bytes32 _orderId) private {
if (orders[_orderId].closeSharesAmount > 0) {
//calcualte the balanceUp/down first
//then reopen the position with MPH amount
// Investment was specified in shares
if (orders[_orderId].closeSharesAmount <= state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId)) {
// Partial closing of long position
orders[_orderId].longSharesOrder = orders[_orderId].closeSharesAmount;
} else {
// Closing of entire long position
orders[_orderId].longSharesOrder = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
}
}
if(
orders[_orderId].longSharesOrder == state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId) &&
orders[_orderId].openMPHTokenAmount > 0
) {
orders[_orderId].shortSharesOrder = orders[_orderId].openMPHTokenAmount.div(
shortShareValue(
orders[_orderId].marketPrice,
orders[_orderId].orderLeverage,
now,
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
orders[_orderId].orderLeverage,
false
));
}
// Investment equals number of shares now.
if (orders[_orderId].longSharesOrder > 0) {
closeLong(_orderId);
}
if (orders[_orderId].shortSharesOrder > 0) {
openShort(_orderId);
}
}
// ----------------------------------------------------------------------------
// openLong(bytes32 _orderId)
// Opens a new long position and computes the new resulting average entry price/spread/leverage.
// Computation is broken down to several instructions for readability.
// ----------------------------------------------------------------------------
function openLong(bytes32 _orderId) private {
address _userId = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
uint256 _newMeanSpread;
uint256 _newMeanLeverage;
// Existing position is virtually liquidated and reopened with current marketPrice
// orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
// _factorLongShares is a factor to adjust the existing longShares via virtual liqudiation and reopening at current market price
uint256 _factorLongShares = state.getMeanEntryLeverage(_userId, _marketId);
if (_factorLongShares < PRECISION) {
_factorLongShares = PRECISION;
}
_factorLongShares = _factorLongShares.sub(PRECISION);
_factorLongShares = _factorLongShares.mul(state.getMeanEntryPrice(_userId, _marketId)).div(orders[_orderId].marketPrice);
if (state.getMeanEntryLeverage(_userId, _marketId) > _factorLongShares) {
_factorLongShares = state.getMeanEntryLeverage(_userId, _marketId).sub(_factorLongShares);
} else {
_factorLongShares = 0;
}
uint256 _adjustedLongShares = _factorLongShares.mul(state.getLongShares(_userId, _marketId)).div(PRECISION);
// _newMeanLeverage is the weighted leverage of the existing position and the new position
_newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId).mul(_adjustedLongShares);
_newMeanLeverage = _newMeanLeverage.add(orders[_orderId].orderLeverage.mul(orders[_orderId].longSharesOrder));
_newMeanLeverage = _newMeanLeverage.div(_adjustedLongShares.add(orders[_orderId].longSharesOrder));
// _newMeanSpread is the weighted spread of the existing position and the new position
_newMeanSpread = state.getMeanEntrySpread(_userId, _marketId).mul(state.getLongShares(_userId, _marketId));
_newMeanSpread = _newMeanSpread.add(orders[_orderId].marketSpread.mul(orders[_orderId].longSharesOrder));
_newMeanSpread = _newMeanSpread.div(_adjustedLongShares.add(orders[_orderId].longSharesOrder));
orders[_orderId].balanceDown = orders[_orderId].longSharesOrder.mul(orders[_orderId].marketPrice).add(
orders[_orderId].longSharesOrder.mul(orders[_orderId].marketSpread).mul(orders[_orderId].orderLeverage).div(PRECISION)
);
orders[_orderId].balanceUp = 0;
orders[_orderId].newLongShares = _adjustedLongShares.add(orders[_orderId].longSharesOrder);
orders[_orderId].newShortShares = state.getShortShares(_userId, _marketId);
orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
orders[_orderId].newMeanEntrySpread = _newMeanSpread;
orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;
setPositionInState(_orderId);
}
// ----------------------------------------------------------------------------
// closeLong(bytes32 _orderId)
// Closes an existing long position. Average entry price/spread/leverage do not change.
// ----------------------------------------------------------------------------
function closeLong(bytes32 _orderId) private {
address _userId = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
uint256 _newLongShares = state.getLongShares(_userId, _marketId).sub(orders[_orderId].longSharesOrder);
uint256 _balanceUp = calculateBalanceUp(_orderId);
uint256 _newMeanEntry;
uint256 _newMeanSpread;
uint256 _newMeanLeverage;
if (orders[_orderId].longSharesOrder == state.getLongShares(_userId, _marketId)) {
_newMeanEntry = 0;
_newMeanSpread = 0;
_newMeanLeverage = PRECISION;
} else {
_newMeanEntry = state.getMeanEntryPrice(_userId, _marketId);
_newMeanSpread = state.getMeanEntrySpread(_userId, _marketId);
_newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId);
resetTimestampInOrderToLastUpdated(_orderId);
}
orders[_orderId].balanceDown = 0;
orders[_orderId].balanceUp = _balanceUp;
orders[_orderId].newLongShares = _newLongShares;
orders[_orderId].newShortShares = state.getShortShares(_userId, _marketId);
orders[_orderId].newMeanEntryPrice = _newMeanEntry;
orders[_orderId].newMeanEntrySpread = _newMeanSpread;
orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;
setPositionInState(_orderId);
}
event ResetTimestampInOrder(bytes32 _orderId, uint oldTimestamp, uint newTimestamp);
function resetTimestampInOrderToLastUpdated(bytes32 _orderId) internal {
address userId = orders[_orderId].userId;
bytes32 marketId = orders[_orderId].marketId;
uint lastUpdated = state.getLastUpdated(userId, marketId);
emit ResetTimestampInOrder(_orderId, orders[_orderId].timeStamp, lastUpdated);
orders[_orderId].timeStamp = lastUpdated;
}
// ----------------------------------------------------------------------------
// closeShort(bytes32 _orderId)
// Closes an existing short position. Average entry price/spread/leverage do not change.
// ----------------------------------------------------------------------------
function calculateBalanceUp(bytes32 _orderId) private view returns (uint256 _balanceUp) {
address _userId = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
uint256 _shareValue;
if (orders[_orderId].tradeDirection == false) { //we are selling our long shares
_balanceUp = orders[_orderId].longSharesOrder;
_shareValue = longShareValue(
state.getMeanEntryPrice(_userId, _marketId),
state.getMeanEntryLeverage(_userId, _marketId),
state.getLastUpdated(_userId, _marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
state.getMeanEntryLeverage(_userId, _marketId),
true
);
} else { //we are going long, we are selling our short shares
_balanceUp = orders[_orderId].shortSharesOrder;
_shareValue = shortShareValue(
state.getMeanEntryPrice(_userId, _marketId),
state.getMeanEntryLeverage(_userId, _marketId),
state.getLastUpdated(_userId, _marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
state.getMeanEntryLeverage(_userId, _marketId),
true
);
}
return _balanceUp.mul(_shareValue);
}
function closeShort(bytes32 _orderId) private {
address _userId = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
uint256 _newMeanEntry;
uint256 _newMeanSpread;
uint256 _newMeanLeverage;
uint256 _newShortShares = state.getShortShares(_userId, _marketId).sub(orders[_orderId].shortSharesOrder);
uint256 _balanceUp = calculateBalanceUp(_orderId);
if (orders[_orderId].shortSharesOrder == state.getShortShares(_userId, _marketId)) {
_newMeanEntry = 0;
_newMeanSpread = 0;
_newMeanLeverage = PRECISION;
} else {
_newMeanEntry = state.getMeanEntryPrice(_userId, _marketId);
_newMeanSpread = state.getMeanEntrySpread(_userId, _marketId);
_newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId);
/**
* we need the timestamp of the old order for partial closes, not the new one
*/
resetTimestampInOrderToLastUpdated(_orderId);
}
orders[_orderId].balanceDown = 0;
orders[_orderId].balanceUp = _balanceUp;
orders[_orderId].newLongShares = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
orders[_orderId].newShortShares = _newShortShares;
orders[_orderId].newMeanEntryPrice = _newMeanEntry;
orders[_orderId].newMeanEntrySpread = _newMeanSpread;
orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;
setPositionInState(_orderId);
}
// ----------------------------------------------------------------------------
// openShort(bytes32 _orderId)
// Opens a new short position and computes the new resulting average entry price/spread/leverage.
// Computation is broken down to several instructions for readability.
// ----------------------------------------------------------------------------
function openShort(bytes32 _orderId) private {
address _userId = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
uint256 _newMeanSpread;
uint256 _newMeanLeverage;
//
// Existing position is virtually liquidated and reopened with current marketPrice
// orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
// _factorShortShares is a factor to adjust the existing shortShares via virtual liqudiation and reopening at current market price
uint256 _factorShortShares = state.getMeanEntryLeverage(_userId, _marketId);
if (_factorShortShares < PRECISION) {
_factorShortShares = PRECISION;
}
_factorShortShares = _factorShortShares.add(PRECISION);
_factorShortShares = _factorShortShares.mul(state.getMeanEntryPrice(_userId, _marketId)).div(orders[_orderId].marketPrice);
if (state.getMeanEntryLeverage(_userId, _marketId) < _factorShortShares) {
_factorShortShares = _factorShortShares.sub(state.getMeanEntryLeverage(_userId, _marketId));
} else {
_factorShortShares = 0;
}
uint256 _adjustedShortShares = _factorShortShares.mul(state.getShortShares(_userId, _marketId)).div(PRECISION);
// _newMeanLeverage is the weighted leverage of the existing position and the new position
_newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId).mul(_adjustedShortShares);
_newMeanLeverage = _newMeanLeverage.add(orders[_orderId].orderLeverage.mul(orders[_orderId].shortSharesOrder));
_newMeanLeverage = _newMeanLeverage.div(_adjustedShortShares.add(orders[_orderId].shortSharesOrder));
// _newMeanSpread is the weighted spread of the existing position and the new position
_newMeanSpread = state.getMeanEntrySpread(_userId, _marketId).mul(state.getShortShares(_userId, _marketId));
_newMeanSpread = _newMeanSpread.add(orders[_orderId].marketSpread.mul(orders[_orderId].shortSharesOrder));
_newMeanSpread = _newMeanSpread.div(_adjustedShortShares.add(orders[_orderId].shortSharesOrder));
orders[_orderId].balanceDown = orders[_orderId].shortSharesOrder.mul(orders[_orderId].marketPrice).add(
orders[_orderId].shortSharesOrder.mul(orders[_orderId].marketSpread).mul(orders[_orderId].orderLeverage).div(PRECISION)
);
orders[_orderId].balanceUp = 0;
orders[_orderId].newLongShares = state.getLongShares(_userId, _marketId);
orders[_orderId].newShortShares = _adjustedShortShares.add(orders[_orderId].shortSharesOrder);
orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
orders[_orderId].newMeanEntrySpread = _newMeanSpread;
orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;
setPositionInState(_orderId);
}
function computeLiquidationPrice(bytes32 _orderId) public returns(uint256 _liquidationPrice) {
orders[_orderId].newLiquidationPrice = 0;
if (orders[_orderId].newLongShares > 0) {
orders[_orderId].newLiquidationPrice = getLiquidationPrice(orders[_orderId].newMeanEntryPrice, orders[_orderId].newMeanEntryLeverage, true, orders[_orderId].timeStamp);
}
if (orders[_orderId].newShortShares > 0) {
orders[_orderId].newLiquidationPrice = getLiquidationPrice(orders[_orderId].newMeanEntryPrice, orders[_orderId].newMeanEntryLeverage, false, orders[_orderId].timeStamp);
}
return orders[_orderId].newLiquidationPrice;
}
function getLiquidationPrice(uint256 _newMeanEntryPrice, uint256 _newMeanEntryLeverage, bool _long, uint _positionTimestampInMs) public view returns (uint256 _liquidationPrice) {
if (_long == true) {
_liquidationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.sub(PRECISION)).div(_newMeanEntryLeverage);
_liquidationPrice = _liquidationPrice.add(calculateMarginInterest(_newMeanEntryPrice, _newMeanEntryLeverage, _positionTimestampInMs));
} else {
_liquidationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.add(PRECISION)).div(_newMeanEntryLeverage);
_liquidationPrice = _liquidationPrice.sub(calculateMarginInterest(_newMeanEntryPrice, _newMeanEntryLeverage, _positionTimestampInMs));
}
return _liquidationPrice;
}
// ----------------------------------------------------------------------------
// setPositionInState(bytes32 _orderId)
// Updates the portfolio in Morpher State. Called by closeLong/closeShort/openLong/openShort
// ----------------------------------------------------------------------------
function setPositionInState(bytes32 _orderId) private {
require(state.balanceOf(orders[_orderId].userId).add(orders[_orderId].balanceUp) >= orders[_orderId].balanceDown, "MorpherTradeEngine: insufficient funds.");
computeLiquidationPrice(_orderId);
// Net balanceUp and balanceDown
if (orders[_orderId].balanceUp > orders[_orderId].balanceDown) {
orders[_orderId].balanceUp.sub(orders[_orderId].balanceDown);
orders[_orderId].balanceDown = 0;
} else {
orders[_orderId].balanceDown.sub(orders[_orderId].balanceUp);
orders[_orderId].balanceUp = 0;
}
if (orders[_orderId].balanceUp > 0) {
mintingLimiter.mint(orders[_orderId].userId, orders[_orderId].balanceUp);
}
if (orders[_orderId].balanceDown > 0) {
state.burn(orders[_orderId].userId, orders[_orderId].balanceDown);
}
state.setPosition(
orders[_orderId].userId,
orders[_orderId].marketId,
orders[_orderId].timeStamp,
orders[_orderId].newLongShares,
orders[_orderId].newShortShares,
orders[_orderId].newMeanEntryPrice,
orders[_orderId].newMeanEntrySpread,
orders[_orderId].newMeanEntryLeverage,
orders[_orderId].newLiquidationPrice
);
emit PositionUpdated(
orders[_orderId].userId,
orders[_orderId].marketId,
orders[_orderId].timeStamp,
orders[_orderId].newLongShares,
orders[_orderId].newShortShares,
orders[_orderId].newMeanEntryPrice,
orders[_orderId].newMeanEntrySpread,
orders[_orderId].newMeanEntryLeverage,
orders[_orderId].newLiquidationPrice,
orders[_orderId].balanceUp,
orders[_orderId].balanceDown
);
}
}
pragma solidity 0.5.16;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
pragma solidity 0.5.16;
contract IMorpherStaking {
function lastReward() public view returns (uint256);
function totalShares() public view returns (uint256);
function interestRate() public view returns (uint256);
function lockupPeriod() public view returns (uint256);
function minimumStake() public view returns (uint256);
function stakingAdmin() public view returns (address);
function updatePoolShareValue() public returns (uint256 _newPoolShareValue) ;
function stake(uint256 _amount) public returns (uint256 _poolShares);
function unStake(uint256 _numOfShares) public returns (uint256 _amount);
}
pragma solidity 0.5.16;
contract IMorpherState {
function setPosition(
address _address,
bytes32 _marketId,
uint256 _timeStamp,
uint256 _longShares,
uint256 _shortShares,
uint256 _meanEntryPrice,
uint256 _meanEntrySpread,
uint256 _meanEntryLeverage,
uint256 _liquidationPrice
) public;
function getPosition(
address _address,
bytes32 _marketId
) public view returns (
uint256 _longShares,
uint256 _shortShares,
uint256 _meanEntryPrice,
uint256 _meanEntrySpread,
uint256 _meanEntryLeverage,
uint256 _liquidationPrice
);
function getLastUpdated(address _address, bytes32 _marketId) public view returns (uint256 _lastUpdated);
function transfer(address _from, address _to, uint256 _token) public;
function balanceOf(address _tokenOwner) public view returns (uint256 balance);
function mint(address _address, uint256 _token) public;
function burn(address _address, uint256 _token) public;
function getSideChainOperator() public view returns (address _address);
function inactivityPeriod() public view returns (uint256);
function getSideChainMerkleRootWrittenAtTime() public view returns(uint256 _sideChainMerkleRoot);
function fastTransfersEnabled() public view returns(bool);
function mainChain() public view returns(bool);
function setInactivityPeriod(uint256 _periodLength) public;
function disableFastWithdraws() public;
function setSideChainMerkleRoot(bytes32 _sideChainMerkleRoot) public;
function resetLast24HoursAmountWithdrawn() public;
function set24HourWithdrawLimit(uint256 _limit) public;
function getTokenSentToLinkedChain(address _address) public view returns (uint256 _token);
function getTokenClaimedOnThisChain(address _address) public view returns (uint256 _token);
function getTokenSentToLinkedChainTime(address _address) public view returns (uint256 _timeStamp);
function lastWithdrawLimitReductionTime() public view returns (uint256);
function withdrawLimit24Hours() public view returns (uint256);
function update24HoursWithdrawLimit(uint256 _amount) public;
function last24HoursAmountWithdrawn() public view returns (uint256);
function setTokenSentToLinkedChain(address _address, uint256 _token) public;
function setTokenClaimedOnThisChain(address _address, uint256 _token) public;
function add24HoursWithdrawn(uint256 _amount) public;
function getPositionHash(
address _address,
bytes32 _marketId,
uint256 _timeStamp,
uint256 _longShares,
uint256 _shortShares,
uint256 _meanEntryPrice,
uint256 _meanEntrySpread,
uint256 _meanEntryLeverage,
uint256 _liquidationPrice
) public pure returns (bytes32 _hash);
function getPositionClaimedOnMainChain(bytes32 _positionHash) public view returns (bool _alreadyClaimed);
function setPositionClaimedOnMainChain(bytes32 _positionHash) public;
function getBalanceHash(address _address, uint256 _balance) public pure returns (bytes32 _hash);
function getSideChainMerkleRoot() public view returns(bytes32 _sideChainMerkleRoot);
function getBridgeNonce() public returns (uint256 _nonce);
}pragma solidity 0.5.16;
interface IMorpherToken {
/**
* Emits a {Transfer} event in ERC-20 token contract.
*/
function emitTransfer(address _from, address _to, uint256 _amount) external;
}
pragma solidity 0.5.16;
/**
* @dev These functions deal with verification of Merkle trees (hash trees),
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
require(proof.length < 100, "MerkleProof: proof too long. Use only sibling hashes.");
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash < proofElement) {
// Hash(current computed hash + current element of the proof)
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
// Hash(current element of the proof + current computed hash)
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
// Check if the computed hash (root) is equal to the provided root
return computedHash == root;
}
}
pragma solidity 0.5.16;
import "./MorpherState.sol";
import "./MorpherTradeEngine.sol";
import "./SafeMath.sol";
contract MorpherMintingLimiter {
using SafeMath for uint256;
uint256 public mintingLimit;
uint256 public timeLockingPeriod;
mapping(address => uint256) public escrowedTokens;
mapping(address => uint256) public lockedUntil;
address tradeEngineAddress;
MorpherState state;
event MintingEscrowed(address _user, uint256 _tokenAmount);
event EscrowReleased(address _user, uint256 _tokenAmount);
event MintingDenied(address _user, uint256 _tokenAmount);
event MintingLimitUpdated(uint256 _mintingLimitOld, uint256 _mintingLimitNew);
event TimeLockPeriodUpdated(uint256 _timeLockPeriodOld, uint256 _timeLockPeriodNew);
event TradeEngineAddressSet(address _tradeEngineAddress);
modifier onlyTradeEngine() {
require(msg.sender == tradeEngineAddress, "MorpherMintingLimiter: Only Trade Engine is allowed to call this function");
_;
}
modifier onlyAdministrator() {
require(msg.sender == state.getAdministrator(), "MorpherMintingLimiter: Only Administrator can call this function");
_;
}
constructor(address _stateAddress, uint256 _mintingLimit, uint256 _timeLockingPeriodInSeconds) public {
state = MorpherState(_stateAddress);
mintingLimit = _mintingLimit;
timeLockingPeriod = _timeLockingPeriodInSeconds;
}
function setTradeEngineAddress(address _tradeEngineAddress) public onlyAdministrator {
emit TradeEngineAddressSet(_tradeEngineAddress);
tradeEngineAddress = _tradeEngineAddress;
}
function setMintingLimit(uint256 _newMintingLimit) public onlyAdministrator {
emit MintingLimitUpdated(mintingLimit, _newMintingLimit);
mintingLimit = _newMintingLimit;
}
function setTimeLockingPeriod(uint256 _newTimeLockingPeriodInSeconds) public onlyAdministrator {
emit TimeLockPeriodUpdated(timeLockingPeriod, _newTimeLockingPeriodInSeconds);
timeLockingPeriod = _newTimeLockingPeriodInSeconds;
}
function mint(address _user, uint256 _tokenAmount) public onlyTradeEngine {
if(mintingLimit == 0 || _tokenAmount <= mintingLimit) {
state.mint(_user, _tokenAmount);
} else {
escrowedTokens[_user] = escrowedTokens[_user].add(_tokenAmount);
lockedUntil[_user] = block.timestamp + timeLockingPeriod;
emit MintingEscrowed(_user, _tokenAmount);
}
}
function delayedMint(address _user) public {
require(lockedUntil[_user] <= block.timestamp, "MorpherMintingLimiter: Funds are still time locked");
uint256 sendAmount = escrowedTokens[_user];
escrowedTokens[_user] = 0;
state.mint(_user, sendAmount);
emit EscrowReleased(_user, sendAmount);
}
function adminApprovedMint(address _user, uint256 _tokenAmount) public onlyAdministrator {
escrowedTokens[_user] = escrowedTokens[_user].sub(_tokenAmount);
state.mint(_user, _tokenAmount);
emit EscrowReleased(_user, _tokenAmount);
}
function adminDisapproveMint(address _user, uint256 _tokenAmount) public onlyAdministrator {
escrowedTokens[_user] = escrowedTokens[_user].sub(_tokenAmount);
emit MintingDenied(_user, _tokenAmount);
}
}pragma solidity 0.5.16;
import "./Ownable.sol";
import "./MorpherTradeEngine.sol";
import "./MorpherState.sol";
import "./SafeMath.sol";
// ----------------------------------------------------------------------------------
// Morpher Oracle contract v 2.0
// The oracle initates a new trade by calling trade engine and requesting a new orderId.
// An event is fired by the contract notifying the oracle operator to query a price/liquidation unchecked
// for a market/user and return the information via the callback function. Since calling
// the callback function requires gas, the user must send a fixed amount of Ether when
// creating their order.
// ----------------------------------------------------------------------------------
contract MorpherOracle is Ownable {
MorpherTradeEngine tradeEngine;
MorpherState state; // read only, Oracle doesn't need writing access to state
using SafeMath for uint256;
bool public paused;
bool public useWhiteList; //always false at the moment
uint256 public gasForCallback;
address payable public callBackCollectionAddress;
mapping(address => bool) public callBackAddress;
mapping(address => bool) public whiteList;
mapping(bytes32 => uint256) public priceBelow;
mapping(bytes32 => uint256) public priceAbove;
mapping(bytes32 => uint256) public goodFrom;
mapping(bytes32 => uint256) public goodUntil;
mapping(bytes32 => bool) public orderCancellationRequested;
mapping(bytes32 => address) public orderIdTradeEngineAddress;
address public previousTradeEngineAddress;
address public previousOracleAddress;
// ----------------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------------
event OrderCreated(
bytes32 indexed _orderId,
address indexed _address,
bytes32 indexed _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
bool _tradeDirection,
uint256 _orderLeverage,
uint256 _onlyIfPriceBelow,
uint256 _onlyIfPriceAbove,
uint256 _goodFrom,
uint256 _goodUntil
);
event LiquidationOrderCreated(
bytes32 indexed _orderId,
address _sender,
address indexed _address,
bytes32 indexed _marketId
);
event OrderProcessed(
bytes32 indexed _orderId,
uint256 _price,
uint256 _unadjustedMarketPrice,
uint256 _spread,
uint256 _positionLiquidationTimestamp,
uint256 _timeStamp,
uint256 _newLongShares,
uint256 _newShortShares,
uint256 _newMeanEntry,
uint256 _newMeanSprad,
uint256 _newMeanLeverage,
uint256 _liquidationPrice
);
event OrderFailed(
bytes32 indexed _orderId,
address indexed _address,
bytes32 indexed _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
bool _tradeDirection,
uint256 _orderLeverage,
uint256 _onlyIfPriceBelow,
uint256 _onlyIfPriceAbove,
uint256 _goodFrom,
uint256 _goodUntil
);
event OrderCancelled(
bytes32 indexed _orderId,
address indexed _sender,
address indexed _oracleAddress
);
event AdminOrderCancelled(
bytes32 indexed _orderId,
address indexed _sender,
address indexed _oracleAddress
);
event OrderCancellationRequestedEvent(
bytes32 indexed _orderId,
address indexed _sender
);
event CallbackAddressEnabled(
address indexed _address
);
event CallbackAddressDisabled(
address indexed _address
);
event OraclePaused(
bool _paused
);
event CallBackCollectionAddressChange(
address _address
);
event SetGasForCallback(
uint256 _gasForCallback
);
event LinkTradeEngine(
address _address
);
event LinkMorpherState(
address _address
);
event SetUseWhiteList(
bool _useWhiteList
);
event AddressWhiteListed(
address _address
);
event AddressBlackListed(
address _address
);
event AdminLiquidationOrderCreated(
bytes32 indexed _orderId,
address indexed _address,
bytes32 indexed _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
bool _tradeDirection,
uint256 _orderLeverage
);
/**
* Delisting markets is a function that stops when gas is running low
* if it reached all positions it will emit "DelistMarketComplete"
* otherwise it needs to be re-run.
*/
event DelistMarketIncomplete(bytes32 _marketId, uint256 _processedUntilIndex);
event DelistMarketComplete(bytes32 _marketId);
event LockedPriceForClosingPositions(bytes32 _marketId, uint256 _price);
modifier onlyOracleOperator {
require(isCallbackAddress(msg.sender), "MorpherOracle: Only the oracle operator can call this function.");
_;
}
modifier onlyAdministrator {
require(msg.sender == state.getAdministrator(), "Function can only be called by the Administrator.");
_;
}
modifier notPaused {
require(paused == false, "MorpherOracle: Oracle paused, aborting");
_;
}
constructor(address _tradeEngineAddress, address _morpherState, address _callBackAddress, address payable _gasCollectionAddress, uint256 _gasForCallback, address _coldStorageOwnerAddress, address _previousTradeEngineAddress, address _previousOracleAddress) public {
setTradeEngineAddress(_tradeEngineAddress);
setStateAddress(_morpherState);
enableCallbackAddress(_callBackAddress);
setCallbackCollectionAddress(_gasCollectionAddress);
setGasForCallback(_gasForCallback);
transferOwnership(_coldStorageOwnerAddress);
previousTradeEngineAddress = _previousTradeEngineAddress; //that is the address before updating the trade engine. Can set to 0x0000 if a completely new deployment happens. It is only valid when mid-term updating the tradeengine
previousOracleAddress = _previousOracleAddress; //if we are updating the oracle, then this is the previous oracle address. Can be set to 0x00 if a completely new deployment happens.
}
// ----------------------------------------------------------------------------------
// Setter/getter functions for trade engine address, oracle operator (callback) address,
// and prepaid gas limit for callback function
// ----------------------------------------------------------------------------------
function setTradeEngineAddress(address _address) public onlyOwner {
tradeEngine = MorpherTradeEngine(_address);
emit LinkTradeEngine(_address);
}
function setStateAddress(address _address) public onlyOwner {
state = MorpherState(_address);
emit LinkMorpherState(_address);
}
function overrideGasForCallback(uint256 _gasForCallback) public onlyOwner {
gasForCallback = _gasForCallback;
emit SetGasForCallback(_gasForCallback);
}
function setGasForCallback(uint256 _gasForCallback) private {
gasForCallback = _gasForCallback;
emit SetGasForCallback(_gasForCallback);
}
function enableCallbackAddress(address _address) public onlyOwner {
callBackAddress[_address] = true;
emit CallbackAddressEnabled(_address);
}
function disableCallbackAddress(address _address) public onlyOwner {
callBackAddress[_address] = false;
emit CallbackAddressDisabled(_address);
}
function isCallbackAddress(address _address) public view returns (bool _isCallBackAddress) {
return callBackAddress[_address];
}
function setCallbackCollectionAddress(address payable _address) public onlyOwner {
callBackCollectionAddress = _address;
emit CallBackCollectionAddressChange(_address);
}
function getAdministrator() public view returns(address _administrator) {
return state.getAdministrator();
}
// ----------------------------------------------------------------------------------
// Oracle Owner can use a whitelist and authorize individual addresses
// ----------------------------------------------------------------------------------
function setUseWhiteList(bool _useWhiteList) public onlyOracleOperator {
require(false, "MorpherOracle: Cannot use this functionality in the oracle at the moment");
useWhiteList = _useWhiteList;
emit SetUseWhiteList(_useWhiteList);
}
function setWhiteList(address _whiteList) public onlyOracleOperator {
whiteList[_whiteList] = true;
emit AddressWhiteListed(_whiteList);
}
function setBlackList(address _blackList) public onlyOracleOperator {
whiteList[_blackList] = false;
emit AddressBlackListed(_blackList);
}
function isWhiteListed(address _address) public view returns (bool _whiteListed) {
if (useWhiteList == false || whiteList[_address] == true) {
_whiteListed = true;
}
return(_whiteListed);
}
// ----------------------------------------------------------------------------------
// emitOrderFailed
// Can be called by Oracle Operator to notifiy user of failed order
// ----------------------------------------------------------------------------------
function emitOrderFailed(
bytes32 _orderId,
address _address,
bytes32 _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
bool _tradeDirection,
uint256 _orderLeverage,
uint256 _onlyIfPriceBelow,
uint256 _onlyIfPriceAbove,
uint256 _goodFrom,
uint256 _goodUntil
) public onlyOracleOperator {
emit OrderFailed(
_orderId,
_address,
_marketId,
_closeSharesAmount,
_openMPHTokenAmount,
_tradeDirection,
_orderLeverage,
_onlyIfPriceBelow,
_onlyIfPriceAbove,
_goodFrom,
_goodUntil);
}
// ----------------------------------------------------------------------------------
// createOrder(bytes32 _marketId, bool _tradeAmountGivenInShares, uint256 _tradeAmount, bool _tradeDirection, uint256 _orderLeverage)
// Request a new orderId from trade engine and fires event for price/liquidation check request.
// ----------------------------------------------------------------------------------
function createOrder(
bytes32 _marketId,
uint256 _closeSharesAmount,
uint256 _openMPHTokenAmount,
bool _tradeDirection,
uint256 _orderLeverage,
uint256 _onlyIfPriceAbove,
uint256 _onlyIfPriceBelow,
uint256 _goodUntil,
uint256 _goodFrom
) public payable notPaused returns (bytes32 _orderId) {
require(isWhiteListed(msg.sender),"MorpherOracle: Address not eligible to create an order.");
if (gasForCallback > 0) {
require(msg.value >= gasForCallback, "MorpherOracle: Must transfer gas costs for Oracle Callback function.");
callBackCollectionAddress.transfer(msg.value);
}
_orderId = tradeEngine.requestOrderId(msg.sender, _marketId, _closeSharesAmount, _openMPHTokenAmount, _tradeDirection, _orderLeverage);
orderIdTradeEngineAddress[_orderId] = address(tradeEngine);
//if the market was deactivated, and the trader didn't fail yet, then we got an orderId to close the position with a locked in price
if(state.getMarketActive(_marketId) == false) {
//price will come from the position where price is stored forever
tradeEngine.processOrder(_orderId, tradeEngine.getDeactivatedMarketPrice(_marketId), 0, 0, now.mul(1000));
emit OrderProcessed(
_orderId,
tradeEngine.getDeactivatedMarketPrice(_marketId),
0,
0,
0,
now.mul(1000),
0,
0,
0,
0,
0,
0
);
} else {
priceAbove[_orderId] = _onlyIfPriceAbove;
priceBelow[_orderId] = _onlyIfPriceBelow;
goodFrom[_orderId] = _goodFrom;
goodUntil[_orderId] = _goodUntil;
emit OrderCreated(
_orderId,
msg.sender,
_marketId,
_closeSharesAmount,
_openMPHTokenAmount,
_tradeDirection,
_orderLeverage,
_onlyIfPriceBelow,
_onlyIfPriceAbove,
_goodFrom,
_goodUntil
);
}
return _orderId;
}
function getTradeEngineFromOrderId(bytes32 _orderId) public view returns (address) {
//get the current trade engine
if(orderIdTradeEngineAddress[_orderId] != address(0)){
return orderIdTradeEngineAddress[_orderId];
}
//todo for later
//we can't do recursively call the oracle.getTradeEngineFromOrderId here, because the previously deployed oracle
//doesn't have this function yet. We can uncomment this in later updates of the oracle
// if(previousOracleAddress !== address(0)) {
// MorpherOracle _oracle = MorpherOracle(previousOracleAddress)
// return _oracle.getTradeEngineFromOrderId(_orderId);
// }
//nothing in there, take the previous tradeEngine then.
return previousTradeEngineAddress;
}
function initiateCancelOrder(bytes32 _orderId) public {
MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
require(orderCancellationRequested[_orderId] == false, "MorpherOracle: Order was already canceled.");
(address userId, , , , , , ) = _tradeEngine.getOrder(_orderId);
require(userId == msg.sender, "MorpherOracle: Only the user can request an order cancellation.");
orderCancellationRequested[_orderId] = true;
emit OrderCancellationRequestedEvent(_orderId, msg.sender);
}
// ----------------------------------------------------------------------------------
// cancelOrder(bytes32 _orderId)
// User or Administrator can cancel their own orders before the _callback has been executed
// ----------------------------------------------------------------------------------
function cancelOrder(bytes32 _orderId) public onlyOracleOperator {
require(orderCancellationRequested[_orderId] == true, "MorpherOracle: Order-Cancellation was not requested.");
MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
(address userId, , , , , , ) = _tradeEngine.getOrder(_orderId);
_tradeEngine.cancelOrder(_orderId, userId);
clearOrderConditions(_orderId);
emit OrderCancelled(
_orderId,
userId,
msg.sender
);
}
// ----------------------------------------------------------------------------------
// adminCancelOrder(bytes32 _orderId)
// Administrator can cancel before the _callback has been executed to provide an updateOrder functionality
// ----------------------------------------------------------------------------------
function adminCancelOrder(bytes32 _orderId) public onlyOracleOperator {
MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
(address userId, , , , , , ) = _tradeEngine.getOrder(_orderId);
_tradeEngine.cancelOrder(_orderId, userId);
clearOrderConditions(_orderId);
emit AdminOrderCancelled(
_orderId,
userId,
msg.sender
);
}
function getGoodUntil(bytes32 _orderId) public view returns(uint) {
if(goodUntil[_orderId] > 0) {
return goodUntil[_orderId];
}
//just return the old one
if(previousOracleAddress != address(0)) {
MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
return _oldOracle.goodUntil(_orderId);
}
return 0;
}
function getGoodFrom(bytes32 _orderId) public view returns(uint) {
if(goodFrom[_orderId] > 0) {
return goodFrom[_orderId];
}
//just return the old one
if(previousOracleAddress != address(0)) {
MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
return _oldOracle.goodFrom(_orderId);
}
return 0;
}
function getPriceAbove(bytes32 _orderId) public view returns(uint) {
if(priceAbove[_orderId] > 0) {
return priceAbove[_orderId];
}
//just return the old one
if(previousOracleAddress != address(0)) {
MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
return _oldOracle.priceAbove(_orderId);
}
return 0;
}
function getPriceBelow(bytes32 _orderId) public view returns(uint) {
if(priceBelow[_orderId] > 0) {
return priceBelow[_orderId];
}
//just return the old one
if(previousOracleAddress != address(0)) {
MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
return _oldOracle.priceBelow(_orderId);
}
return 0;
}
// ------------------------------------------------------------------------
// checkOrderConditions(bytes32 _orderId, uint256 _price)
// Checks if callback satisfies the order conditions
// ------------------------------------------------------------------------
function checkOrderConditions(bytes32 _orderId, uint256 _price) public view returns (bool _conditionsMet) {
_conditionsMet = true;
if (now > getGoodUntil(_orderId) && getGoodUntil(_orderId) > 0) {
_conditionsMet = false;
}
if (now < getGoodFrom(_orderId) && getGoodFrom(_orderId) > 0) {
_conditionsMet = false;
}
if(getPriceAbove(_orderId) > 0 && getPriceBelow(_orderId) > 0) {
if(_price < getPriceAbove(_orderId) && _price > getPriceBelow(_orderId)) {
_conditionsMet = false;
}
} else {
if (_price < getPriceAbove(_orderId) && getPriceAbove(_orderId) > 0) {
_conditionsMet = false;
}
if (_price > getPriceBelow(_orderId) && getPriceBelow(_orderId) > 0) {
_conditionsMet = false;
}
}
return _conditionsMet;
}
// ----------------------------------------------------------------------------------
// Deletes parameters of cancelled or processed orders
// ----------------------------------------------------------------------------------
function clearOrderConditions(bytes32 _orderId) internal {
priceAbove[_orderId] = 0;
priceBelow[_orderId] = 0;
goodFrom[_orderId] = 0;
goodUntil[_orderId] = 0;
}
// ----------------------------------------------------------------------------------
// Pausing/unpausing the Oracle contract
// ----------------------------------------------------------------------------------
function pauseOracle() public onlyOwner {
paused = true;
emit OraclePaused(true);
}
function unpauseOracle() public onlyOwner {
paused = false;
emit OraclePaused(false);
}
// ----------------------------------------------------------------------------------
// createLiquidationOrder(address _address, bytes32 _marketId)
// Checks if position has been liquidated since last check. Requires gas for callback
// function. Anyone can issue a liquidation order for any other address and market.
// ----------------------------------------------------------------------------------
function createLiquidationOrder(
address _address,
bytes32 _marketId
) public notPaused onlyOracleOperator payable returns (bytes32 _orderId) {
if (gasForCallback > 0) {
require(msg.value >= gasForCallback, "MorpherOracle: Must transfer gas costs for Oracle Callback function.");
callBackCollectionAddress.transfer(msg.value);
}
_orderId = tradeEngine.requestOrderId(_address, _marketId, 0, 0, true, 10**8);
orderIdTradeEngineAddress[_orderId] = address(tradeEngine);
emit LiquidationOrderCreated(_orderId, msg.sender, _address, _marketId);
return _orderId;
}
// ----------------------------------------------------------------------------------
// __callback(bytes32 _orderId, uint256 _price, uint256 _spread, uint256 _liquidationTimestamp, uint256 _timeStamp)
// Called by the oracle operator. Writes price/spread/liquidiation check to the blockchain.
// Trade engine processes the order and updates the portfolio in state if successful.
// ----------------------------------------------------------------------------------
function __callback(
bytes32 _orderId,
uint256 _price,
uint256 _unadjustedMarketPrice,
uint256 _spread,
uint256 _liquidationTimestamp,
uint256 _timeStamp,
uint256 _gasForNextCallback
) public onlyOracleOperator notPaused returns (uint256 _newLongShares, uint256 _newShortShares, uint256 _newMeanEntry, uint256 _newMeanSpread, uint256 _newMeanLeverage, uint256 _liquidationPrice) {
require(checkOrderConditions(_orderId, _price), 'MorpherOracle Error: Order Conditions are not met');
MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
(
_newLongShares,
_newShortShares,
_newMeanEntry,
_newMeanSpread,
_newMeanLeverage,
_liquidationPrice
) = _tradeEngine.processOrder(_orderId, _price, _spread, _liquidationTimestamp, _timeStamp);
clearOrderConditions(_orderId);
emit OrderProcessed(
_orderId,
_price,
_unadjustedMarketPrice,
_spread,
_liquidationTimestamp,
_timeStamp,
_newLongShares,
_newShortShares,
_newMeanEntry,
_newMeanSpread,
_newMeanLeverage,
_liquidationPrice
);
setGasForCallback(_gasForNextCallback);
return (_newLongShares, _newShortShares, _newMeanEntry, _newMeanSpread, _newMeanLeverage, _liquidationPrice);
}
// ----------------------------------------------------------------------------------
// delistMarket(bytes32 _marketId)
// Administrator closes out all existing positions on _marketId market at current prices
// ----------------------------------------------------------------------------------
uint delistMarketFromIx = 0;
function delistMarket(bytes32 _marketId, bool _startFromScratch) public onlyAdministrator {
require(state.getMarketActive(_marketId) == true, "Market must be active to process position liquidations.");
// If no _fromIx and _toIx specified, do entire _list
if (_startFromScratch) {
delistMarketFromIx = 0;
}
uint _toIx = state.getMaxMappingIndex(_marketId);
address _address;
for (uint256 i = delistMarketFromIx; i <= _toIx; i++) {
if(gasleft() < 250000 && i != _toIx) { //stop if there's not enough gas to write the next transaction
delistMarketFromIx = i;
emit DelistMarketIncomplete(_marketId, _toIx);
return;
}
_address = state.getExposureMappingAddress(_marketId, i);
adminLiquidationOrder(_address, _marketId);
}
emit DelistMarketComplete(_marketId);
}
/**
* Course of action would be:
* 1. de-activate market through state
* 2. set the Deactivated Market Price
* 3. let users still close their positions
*/
function setDeactivatedMarketPrice(bytes32 _marketId, uint256 _price) public onlyAdministrator {
//todo updateable tradeEngine
tradeEngine.setDeactivatedMarketPrice(_marketId, _price);
emit LockedPriceForClosingPositions(_marketId, _price);
}
// ----------------------------------------------------------------------------------
// adminLiquidationOrder(address _address, bytes32 _marketId)
// Administrator closes out an existing position of _address on _marketId market at current price
// ----------------------------------------------------------------------------------
function adminLiquidationOrder(
address _address,
bytes32 _marketId
) public onlyAdministrator returns (bytes32 _orderId) {
uint256 _positionLongShares = state.getLongShares(_address, _marketId);
uint256 _positionShortShares = state.getShortShares(_address, _marketId);
if (_positionLongShares > 0) {
_orderId = tradeEngine.requestOrderId(_address, _marketId, _positionLongShares, 0, false, 10**8);
emit AdminLiquidationOrderCreated(_orderId, _address, _marketId, _positionLongShares, 0, false, 10**8);
}
if (_positionShortShares > 0) {
_orderId = tradeEngine.requestOrderId(_address, _marketId, _positionShortShares, 0, true, 10**8);
emit AdminLiquidationOrderCreated(_orderId, _address, _marketId, _positionShortShares, 0, true, 10**8);
}
orderIdTradeEngineAddress[_orderId] = address(tradeEngine);
return _orderId;
}
// ----------------------------------------------------------------------------------
// Auxiliary function to hash a string market name i.e.
// "CRYPTO_BTC" => 0x0bc89e95f9fdaab7e8a11719155f2fd638cb0f665623f3d12aab71d1a125daf9;
// ----------------------------------------------------------------------------------
function stringToHash(string memory _source) public pure returns (bytes32 _result) {
return keccak256(abi.encodePacked(_source));
}
}
pragma solidity 0.5.16;
import "./Ownable.sol";
import "./SafeMath.sol";
import "./IMorpherState.sol";
// ----------------------------------------------------------------------------------
// Staking Morpher Token generates interest
// The interest is set to 0.015% a day or ~5.475% in the first year
// Stakers will be able to vote on all ProtocolDecisions in MorpherGovernance (soon...)
// There is a lockup after staking or topping up (30 days) and a minimum stake (100k MPH)
// ----------------------------------------------------------------------------------
contract MorpherStaking is Ownable {
using SafeMath for uint256;
IMorpherState state;
uint256 constant PRECISION = 10**8;
uint256 constant INTERVAL = 1 days;
//mapping(address => uint256) private poolShares;
//mapping(address => uint256) private lockup;
uint256 public poolShareValue = PRECISION;
uint256 public lastReward;
uint256 public totalShares;
uint256 public interestRate = 15000; // 0.015% per day initially, diminishing returns over time
uint256 public lockupPeriod = 30 days; // to prevent tactical staking and ensure smooth governance
uint256 public minimumStake = 10**23; // 100k MPH minimum
address public stakingAdmin;
address public stakingAddress = 0x2222222222222222222222222222222222222222;
bytes32 public marketIdStakingMPH = 0x9a31fdde7a3b1444b1befb10735dcc3b72cbd9dd604d2ff45144352bf0f359a6; //STAKING_MPH
// ----------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------
event SetInterestRate(uint256 newInterestRate);
event SetLockupPeriod(uint256 newLockupPeriod);
event SetMinimumStake(uint256 newMinimumStake);
event LinkState(address stateAddress);
event SetStakingAdmin(address stakingAdmin);
event PoolShareValueUpdated(uint256 indexed lastReward, uint256 poolShareValue);
event StakingRewardsMinted(uint256 indexed lastReward, uint256 delta);
event Staked(address indexed userAddress, uint256 indexed amount, uint256 poolShares, uint256 lockedUntil);
event Unstaked(address indexed userAddress, uint256 indexed amount, uint256 poolShares);
modifier onlyStakingAdmin {
require(msg.sender == stakingAdmin, "MorpherStaking: can only be called by Staking Administrator.");
_;
}
constructor(address _morpherState, address _stakingAdmin) public {
setStakingAdmin(_stakingAdmin);
setMorpherStateAddress(_morpherState);
emit SetLockupPeriod(lockupPeriod);
emit SetMinimumStake(minimumStake);
emit SetInterestRate(interestRate);
lastReward = now;
// missing: transferOwnership to Governance once deployed
}
// ----------------------------------------------------------------------------
// updatePoolShareValue
// Updates the value of the Pool Shares and returns the new value.
// Staking rewards are linear, there is no compound interest.
// ----------------------------------------------------------------------------
function updatePoolShareValue() public returns (uint256 _newPoolShareValue) {
if (now >= lastReward.add(INTERVAL)) {
uint256 _numOfIntervals = now.sub(lastReward).div(INTERVAL);
poolShareValue = poolShareValue.add(_numOfIntervals.mul(interestRate));
lastReward = lastReward.add(_numOfIntervals.mul(INTERVAL));
emit PoolShareValueUpdated(lastReward, poolShareValue);
}
mintStakingRewards();
return poolShareValue;
}
// ----------------------------------------------------------------------------
// Staking rewards are minted if necessary
// ----------------------------------------------------------------------------
function mintStakingRewards() private {
uint256 _targetBalance = poolShareValue.mul(totalShares);
if (state.balanceOf(stakingAddress) < _targetBalance) {
// If there are not enough token held by the contract, mint them
uint256 _delta = _targetBalance.sub(state.balanceOf(stakingAddress));
state.mint(stakingAddress, _delta);
emit StakingRewardsMinted(lastReward, _delta);
}
}
// ----------------------------------------------------------------------------
// stake(uint256 _amount)
// User specifies an amount they intend to stake. Pool Shares are issued accordingly
// and the _amount is transferred to the staking contract
// ----------------------------------------------------------------------------
function stake(uint256 _amount) public returns (uint256 _poolShares) {
require(state.balanceOf(msg.sender) >= _amount, "MorpherStaking: insufficient MPH token balance");
updatePoolShareValue();
_poolShares = _amount.div(poolShareValue);
(uint256 _numOfShares, , , , , ) = state.getPosition(msg.sender, marketIdStakingMPH);
require(minimumStake <= _numOfShares.add(_poolShares).mul(poolShareValue), "MorpherStaking: stake amount lower than minimum stake");
state.transfer(msg.sender, stakingAddress, _poolShares.mul(poolShareValue));
totalShares = totalShares.add(_poolShares);
state.setPosition(msg.sender, marketIdStakingMPH, now.add(lockupPeriod), _numOfShares.add(_poolShares), 0, 0, 0, 0, 0);
emit Staked(msg.sender, _amount, _poolShares, now.add(lockupPeriod));
return _poolShares;
}
// ----------------------------------------------------------------------------
// unstake(uint256 _amount)
// User specifies number of Pool Shares they want to unstake.
// Pool Shares get deleted and the user receives their MPH plus interest
// ----------------------------------------------------------------------------
function unstake(uint256 _numOfShares) public returns (uint256 _amount) {
(uint256 _numOfExistingShares, , , , , ) = state.getPosition(msg.sender, marketIdStakingMPH);
require(_numOfShares <= _numOfExistingShares, "MorpherStaking: insufficient pool shares");
uint256 lockedInUntil = state.getLastUpdated(msg.sender, marketIdStakingMPH);
require(now >= lockedInUntil, "MorpherStaking: cannot unstake before lockup expiration");
updatePoolShareValue();
state.setPosition(msg.sender, marketIdStakingMPH, lockedInUntil, _numOfExistingShares.sub(_numOfShares), 0, 0, 0, 0, 0);
totalShares = totalShares.sub(_numOfShares);
_amount = _numOfShares.mul(poolShareValue);
state.transfer(stakingAddress, msg.sender, _amount);
emit Unstaked(msg.sender, _amount, _numOfShares);
return _amount;
}
// ----------------------------------------------------------------------------
// Administrative functions
// ----------------------------------------------------------------------------
function setStakingAdmin(address _address) public onlyOwner {
stakingAdmin = _address;
emit SetStakingAdmin(_address);
}
function setMorpherStateAddress(address _stateAddress) public onlyOwner {
state = IMorpherState(_stateAddress);
emit LinkState(_stateAddress);
}
function setInterestRate(uint256 _interestRate) public onlyStakingAdmin {
interestRate = _interestRate;
emit SetInterestRate(_interestRate);
}
function setLockupPeriodRate(uint256 _lockupPeriod) public onlyStakingAdmin {
lockupPeriod = _lockupPeriod;
emit SetLockupPeriod(_lockupPeriod);
}
function setMinimumStake(uint256 _minimumStake) public onlyStakingAdmin {
minimumStake = _minimumStake;
emit SetMinimumStake(_minimumStake);
}
// ----------------------------------------------------------------------------
// Getter functions
// ----------------------------------------------------------------------------
function getTotalPooledValue() public view returns (uint256 _totalPooled) {
// Only accurate if poolShareValue is up to date
return poolShareValue.mul(totalShares);
}
function getStake(address _address) public view returns (uint256 _poolShares) {
(uint256 _numOfShares, , , , , ) = state.getPosition(_address, marketIdStakingMPH);
return _numOfShares;
}
function getStakeValue(address _address) public view returns(uint256 _value, uint256 _lastUpdate) {
// Only accurate if poolShareValue is up to date
(uint256 _numOfShares, , , , , ) = state.getPosition(_address, marketIdStakingMPH);
return (_numOfShares.mul(poolShareValue), lastReward);
}
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function () external payable {
revert("MorpherStaking: you can't deposit Ether here");
}
}
pragma solidity 0.5.16;
import "./Ownable.sol";
import "./SafeMath.sol";
import "./IMorpherToken.sol";
// ----------------------------------------------------------------------------------
// Data and token balance storage of the Morpher platform
// Writing access is only granted to platform contracts. The contract can be paused
// by an elected platform administrator (see MorpherGovernance) to perform protocol updates.
// ----------------------------------------------------------------------------------
contract MorpherState is Ownable {
using SafeMath for uint256;
bool public mainChain;
uint256 public totalSupply;
uint256 public totalToken;
uint256 public totalInPositions;
uint256 public totalOnOtherChain;
uint256 public maximumLeverage = 10**9; // Leverage precision is 1e8, maximum leverage set to 10 initially
uint256 constant PRECISION = 10**8;
uint256 constant DECIMALS = 18;
uint256 constant REWARDPERIOD = 1 days;
bool public paused = false;
address public morpherGovernance;
address public morpherRewards;
address public administrator;
address public oracleContract;
address public sideChainOperator;
address public morpherBridge;
address public morpherToken;
uint256 public rewardBasisPoints;
uint256 public lastRewardTime;
bytes32 public sideChainMerkleRoot;
uint256 public sideChainMerkleRootWrittenAtTime;
// Set initial withdraw limit from sidechain to 20m token or 2% of initial supply
uint256 public mainChainWithdrawLimit24 = 2 * 10**25;
mapping(address => bool) private stateAccess;
mapping(address => bool) private transferAllowed;
mapping(address => uint256) private balances;
mapping(address => mapping(address => uint256)) private allowed;
mapping(bytes32 => bool) private marketActive;
// ----------------------------------------------------------------------------
// Position struct records virtual futures
// ----------------------------------------------------------------------------
struct position {
uint256 lastUpdated;
uint256 longShares;
uint256 shortShares;
uint256 meanEntryPrice;
uint256 meanEntrySpread;
uint256 meanEntryLeverage;
uint256 liquidationPrice;
bytes32 positionHash;
}
// ----------------------------------------------------------------------------
// A portfolio is an address specific collection of postions
// ----------------------------------------------------------------------------
mapping(address => mapping(bytes32 => position)) private portfolio;
// ----------------------------------------------------------------------------
// Record all addresses that hold a position of a market, needed for clean stock splits
// ----------------------------------------------------------------------------
struct hasExposure {
uint256 maxMappingIndex;
mapping(address => uint256) index;
mapping(uint256 => address) addy;
}
mapping(bytes32 => hasExposure) private exposureByMarket;
// ----------------------------------------------------------------------------
// Bridge Variables
// ----------------------------------------------------------------------------
mapping (address => uint256) private tokenClaimedOnThisChain;
mapping (address => uint256) private tokenSentToLinkedChain;
mapping (address => uint256) private tokenSentToLinkedChainTime;
mapping (bytes32 => bool) private positionClaimedOnMainChain;
uint256 public lastWithdrawLimitReductionTime;
uint256 public last24HoursAmountWithdrawn;
uint256 public withdrawLimit24Hours;
uint256 public inactivityPeriod = 3 days;
uint256 public transferNonce;
bool public fastTransfersEnabled;
// ----------------------------------------------------------------------------
// Sidechain spam protection
// ----------------------------------------------------------------------------
mapping(address => uint256) private lastRequestBlock;
mapping(address => uint256) private numberOfRequests;
uint256 public numberOfRequestsLimit;
// ----------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------
event StateAccessGranted(address indexed whiteList, uint256 indexed blockNumber);
event StateAccessDenied(address indexed blackList, uint256 indexed blockNumber);
event TransfersEnabled(address indexed whiteList);
event TransfersDisabled(address indexed blackList);
event Transfer(address indexed sender, address indexed recipient, uint256 amount);
event Mint(address indexed recipient, uint256 amount, uint256 totalToken);
event Burn(address indexed recipient, uint256 amount, uint256 totalToken);
event NewTotalSupply(uint256 newTotalSupply);
event NewTotalOnOtherChain(uint256 newTotalOnOtherChain);
event NewTotalInPositions(uint256 newTotalOnOtherChain);
event OperatingRewardMinted(address indexed recipient, uint256 amount);
event RewardsChange(address indexed rewardsAddress, uint256 indexed rewardsBasisPoints);
event LastRewardTime(uint256 indexed rewardsTime);
event GovernanceChange(address indexed governanceAddress);
event TokenChange(address indexed tokenAddress);
event AdministratorChange(address indexed administratorAddress);
event OracleChange(address indexed oracleContract);
event MaximumLeverageChange(uint256 maxLeverage);
event MarketActivated(bytes32 indexed activateMarket);
event MarketDeActivated(bytes32 indexed deActivateMarket);
event BridgeChange(address _bridgeAddress);
event SideChainMerkleRootUpdate(bytes32 indexed sideChainMerkleRoot);
event NewSideChainOperator(address indexed sideChainOperator);
event NumberOfRequestsLimitUpdate(uint256 _numberOfRequests);
event MainChainWithdrawLimitUpdate(uint256 indexed mainChainWithdrawLimit24);
event TokenSentToLinkedChain(address _address, uint256 _token, uint256 _totalTokenSent, bytes32 indexed _tokenSentToLinkedChainHash);
event TransferredTokenClaimed(address _address, uint256 _token);
event LastWithdrawAt();
event RollingWithdrawnAmountUpdated(uint256 _last24HoursAmountWithdrawn, uint256 _lastWithdrawLimitReductionTime);
event WithdrawLimitUpdated(uint256 _amount);
event InactivityPeriodUpdated(uint256 _periodLength);
event FastWithdrawsDisabled();
event NewBridgeNonce(uint256 _transferNonce);
event Last24HoursAmountWithdrawnReset();
event StatePaused(address administrator, bool _paused);
event SetAllowance(address indexed sender, address indexed spender, uint256 tokens);
event SetPosition(bytes32 indexed positionHash,
address indexed sender,
bytes32 indexed marketId,
uint256 timeStamp,
uint256 longShares,
uint256 shortShares,
uint256 meanEntryPrice,
uint256 meanEntrySpread,
uint256 meanEntryLeverage,
uint256 liquidationPrice
);
event SetBalance(address indexed account, uint256 balance, bytes32 indexed balanceHash);
event TokenTransferredToOtherChain(address indexed account, uint256 tokenTransferredToOtherChain, bytes32 indexed transferHash);
modifier notPaused {
require(paused == false, "MorpherState: Contract paused, aborting");
_;
}
modifier onlyPlatform {
require(stateAccess[msg.sender] == true, "MorpherState: Only Platform is allowed to execute operation.");
_;
}
modifier onlyGovernance {
require(msg.sender == getGovernance(), "MorpherState: Calling contract not the Governance Contract. Aborting.");
_;
}
modifier onlyAdministrator {
require(msg.sender == getAdministrator(), "MorpherState: Caller is not the Administrator. Aborting.");
_;
}
modifier onlySideChainOperator {
require(msg.sender == sideChainOperator, "MorpherState: Caller is not the Sidechain Operator. Aborting.");
_;
}
modifier canTransfer(address sender) {
require(getCanTransfer(sender), "MorpherState: Caller may not transfer token. Aborting.");
_;
}
modifier onlyBridge {
require(msg.sender == getMorpherBridge(), "MorpherState: Caller is not the Bridge. Aborting.");
_;
}
modifier onlyMainChain {
require(mainChain == true, "MorpherState: Can only be called on mainchain.");
_;
}
modifier onlySideChain {
require(mainChain == false, "MorpherState: Can only be called on mainchain.");
_;
}
constructor(bool _mainChain, address _sideChainOperator, address _morpherTreasury) public {
// @Deployer: Transfer State Ownership to cold storage address after deploying protocol
mainChain = _mainChain; // true for Ethereum, false for Morpher PoA sidechain
setLastRewardTime(now);
uint256 _sideChainMint = 575000000 * 10**(DECIMALS);
uint256 _mainChainMint = 425000000 * 10**(DECIMALS);
administrator = owner(); //first set the owner as administrator
morpherGovernance = owner(); //first set the owner as governance
grantAccess(owner());
setSideChainOperator(owner());
if (mainChain == false) { // Create token only on sidechain
balances[owner()] = _sideChainMint; // Create airdrop and team token on sidechain
totalToken = _sideChainMint;
emit Mint(owner(), balanceOf(owner()), _sideChainMint);
setRewardBasisPoints(0); // Reward is minted on mainchain
setRewardAddress(address(0));
setTotalOnOtherChain(_mainChainMint);
} else {
balances[owner()] = _mainChainMint; // Create treasury and investor token on mainchain
totalToken = _mainChainMint;
emit Mint(owner(), balanceOf(owner()), _mainChainMint);
setRewardBasisPoints(15000); // 15000 / PRECISION = 0.00015
setRewardAddress(_morpherTreasury);
setTotalOnOtherChain(_sideChainMint);
}
fastTransfersEnabled = true;
setNumberOfRequestsLimit(3);
setMainChainWithdrawLimit(totalSupply / 50);
setSideChainOperator(_sideChainOperator);
denyAccess(owner());
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for market wise exposure
// ----------------------------------------------------------------------------
function getMaxMappingIndex(bytes32 _marketId) public view returns(uint256 _maxMappingIndex) {
return exposureByMarket[_marketId].maxMappingIndex;
}
function getExposureMappingIndex(bytes32 _marketId, address _address) public view returns(uint256 _mappingIndex) {
return exposureByMarket[_marketId].index[_address];
}
function getExposureMappingAddress(bytes32 _marketId, uint256 _mappingIndex) public view returns(address _address) {
return exposureByMarket[_marketId].addy[_mappingIndex];
}
function setMaxMappingIndex(bytes32 _marketId, uint256 _maxMappingIndex) public onlyPlatform {
exposureByMarket[_marketId].maxMappingIndex = _maxMappingIndex;
}
function setExposureMapping(bytes32 _marketId, address _address, uint256 _index) public onlyPlatform {
setExposureMappingIndex(_marketId, _address, _index);
setExposureMappingAddress(_marketId, _address, _index);
}
function setExposureMappingIndex(bytes32 _marketId, address _address, uint256 _index) public onlyPlatform {
exposureByMarket[_marketId].index[_address] = _index;
}
function setExposureMappingAddress(bytes32 _marketId, address _address, uint256 _index) public onlyPlatform {
exposureByMarket[_marketId].addy[_index] = _address;
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for bridge variables
// ----------------------------------------------------------------------------
function setTokenClaimedOnThisChain(address _address, uint256 _token) public onlyBridge {
tokenClaimedOnThisChain[_address] = _token;
emit TransferredTokenClaimed(_address, _token);
}
function getTokenClaimedOnThisChain(address _address) public view returns (uint256 _token) {
return tokenClaimedOnThisChain[_address];
}
function setTokenSentToLinkedChain(address _address, uint256 _token) public onlyBridge {
tokenSentToLinkedChain[_address] = _token;
tokenSentToLinkedChainTime[_address] = now;
emit TokenSentToLinkedChain(_address, _token, tokenSentToLinkedChain[_address], getBalanceHash(_address, tokenSentToLinkedChain[_address]));
}
function getTokenSentToLinkedChain(address _address) public view returns (uint256 _token) {
return tokenSentToLinkedChain[_address];
}
function getTokenSentToLinkedChainTime(address _address) public view returns (uint256 _timeStamp) {
return tokenSentToLinkedChainTime[_address];
}
function add24HoursWithdrawn(uint256 _amount) public onlyBridge {
last24HoursAmountWithdrawn = last24HoursAmountWithdrawn.add(_amount);
emit RollingWithdrawnAmountUpdated(last24HoursAmountWithdrawn, lastWithdrawLimitReductionTime);
}
function update24HoursWithdrawLimit(uint256 _amount) public onlyBridge {
if (last24HoursAmountWithdrawn > _amount) {
last24HoursAmountWithdrawn = last24HoursAmountWithdrawn.sub(_amount);
} else {
last24HoursAmountWithdrawn = 0;
}
lastWithdrawLimitReductionTime = now;
emit RollingWithdrawnAmountUpdated(last24HoursAmountWithdrawn, lastWithdrawLimitReductionTime);
}
function set24HourWithdrawLimit(uint256 _limit) public onlyBridge {
withdrawLimit24Hours = _limit;
emit WithdrawLimitUpdated(_limit);
}
function resetLast24HoursAmountWithdrawn() public onlyBridge {
last24HoursAmountWithdrawn = 0;
emit Last24HoursAmountWithdrawnReset();
}
function setInactivityPeriod(uint256 _periodLength) public onlyBridge {
inactivityPeriod = _periodLength;
emit InactivityPeriodUpdated(_periodLength);
}
function getBridgeNonce() public onlyBridge returns (uint256 _nonce) {
transferNonce++;
emit NewBridgeNonce(transferNonce);
return transferNonce;
}
function disableFastWithdraws() public onlyBridge {
fastTransfersEnabled = false;
emit FastWithdrawsDisabled();
}
function setPositionClaimedOnMainChain(bytes32 _positionHash) public onlyBridge {
positionClaimedOnMainChain[_positionHash] = true;
}
function getPositionClaimedOnMainChain(bytes32 _positionHash) public view returns (bool _alreadyClaimed) {
return positionClaimedOnMainChain[_positionHash];
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for spam protection
// ----------------------------------------------------------------------------
function setLastRequestBlock(address _address) public onlyPlatform {
lastRequestBlock[_address] = block.number;
}
function getLastRequestBlock(address _address) public view returns(uint256 _lastRequestBlock) {
return lastRequestBlock[_address];
}
function setNumberOfRequests(address _address, uint256 _numberOfRequests) public onlyPlatform {
numberOfRequests[_address] = _numberOfRequests;
}
function increaseNumberOfRequests(address _address) public onlyPlatform{
numberOfRequests[_address]++;
}
function getNumberOfRequests(address _address) public view returns(uint256 _numberOfRequests) {
return numberOfRequests[_address];
}
function setNumberOfRequestsLimit(uint256 _numberOfRequestsLimit) public onlyPlatform {
numberOfRequestsLimit = _numberOfRequestsLimit;
emit NumberOfRequestsLimitUpdate(_numberOfRequestsLimit);
}
function getNumberOfRequestsLimit() public view returns (uint256 _numberOfRequestsLimit) {
return numberOfRequestsLimit;
}
function setMainChainWithdrawLimit(uint256 _mainChainWithdrawLimit24) public onlyGovernance {
mainChainWithdrawLimit24 = _mainChainWithdrawLimit24;
emit MainChainWithdrawLimitUpdate(_mainChainWithdrawLimit24);
}
function getMainChainWithdrawLimit() public view returns (uint256 _mainChainWithdrawLimit24) {
return mainChainWithdrawLimit24;
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for state access
// ----------------------------------------------------------------------------
function grantAccess(address _address) public onlyAdministrator {
stateAccess[_address] = true;
emit StateAccessGranted(_address, block.number);
}
function denyAccess(address _address) public onlyAdministrator {
stateAccess[_address] = false;
emit StateAccessDenied(_address, block.number);
}
function getStateAccess(address _address) public view returns(bool _hasAccess) {
return stateAccess[_address];
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for addresses that can transfer tokens (sidechain only)
// ----------------------------------------------------------------------------
function enableTransfers(address _address) public onlyAdministrator {
transferAllowed[_address] = true;
emit TransfersEnabled(_address);
}
function disableTransfers(address _address) public onlyAdministrator {
transferAllowed[_address] = false;
emit TransfersDisabled(_address);
}
function getCanTransfer(address _address) public view returns(bool _hasAccess) {
return mainChain || transferAllowed[_address];
}
// ----------------------------------------------------------------------------
// Minting/burning/transfer of token
// ----------------------------------------------------------------------------
function transfer(address _from, address _to, uint256 _token) public onlyPlatform notPaused canTransfer(_from) {
require(balances[_from] >= _token, "MorpherState: Not enough token.");
balances[_from] = balances[_from].sub(_token);
balances[_to] = balances[_to].add(_token);
IMorpherToken(morpherToken).emitTransfer(_from, _to, _token);
emit Transfer(_from, _to, _token);
emit SetBalance(_from, balances[_from], getBalanceHash(_from, balances[_from]));
emit SetBalance(_to, balances[_to], getBalanceHash(_to, balances[_to]));
}
function mint(address _address, uint256 _token) public onlyPlatform notPaused {
balances[_address] = balances[_address].add(_token);
totalToken = totalToken.add(_token);
updateTotalSupply();
IMorpherToken(morpherToken).emitTransfer(address(0), _address, _token);
emit Mint(_address, _token, totalToken);
emit SetBalance(_address, balances[_address], getBalanceHash(_address, balances[_address]));
}
function burn(address _address, uint256 _token) public onlyPlatform notPaused {
require(balances[_address] >= _token, "MorpherState: Not enough token.");
balances[_address] = balances[_address].sub(_token);
totalToken = totalToken.sub(_token);
updateTotalSupply();
IMorpherToken(morpherToken).emitTransfer(_address, address(0), _token);
emit Burn(_address, _token, totalToken);
emit SetBalance(_address, balances[_address], getBalanceHash(_address, balances[_address]));
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for balance and token functions (ERC20)
// ----------------------------------------------------------------------------
function updateTotalSupply() private {
totalSupply = totalToken.add(totalInPositions).add(totalOnOtherChain);
emit NewTotalSupply(totalSupply);
}
function setTotalInPositions(uint256 _totalInPositions) public onlyAdministrator {
totalInPositions = _totalInPositions;
updateTotalSupply();
emit NewTotalInPositions(_totalInPositions);
}
function setTotalOnOtherChain(uint256 _newTotalOnOtherChain) public onlySideChainOperator {
totalOnOtherChain = _newTotalOnOtherChain;
updateTotalSupply();
emit NewTotalOnOtherChain(_newTotalOnOtherChain);
}
function balanceOf(address _tokenOwner) public view returns (uint256 balance) {
return balances[_tokenOwner];
}
function setAllowance(address _from, address _spender, uint256 _tokens) public onlyPlatform {
allowed[_from][_spender] = _tokens;
emit SetAllowance(_from, _spender, _tokens);
}
function getAllowance(address _tokenOwner, address spender) public view returns (uint256 remaining) {
return allowed[_tokenOwner][spender];
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for platform roles
// ----------------------------------------------------------------------------
function setGovernanceContract(address _newGovernanceContractAddress) public onlyGovernance {
morpherGovernance = _newGovernanceContractAddress;
emit GovernanceChange(_newGovernanceContractAddress);
}
function getGovernance() public view returns (address _governanceContract) {
return morpherGovernance;
}
function setMorpherBridge(address _newBridge) public onlyGovernance {
morpherBridge = _newBridge;
emit BridgeChange(_newBridge);
}
function getMorpherBridge() public view returns (address _currentBridge) {
return morpherBridge;
}
function setOracleContract(address _newOracleContract) public onlyGovernance {
oracleContract = _newOracleContract;
emit OracleChange(_newOracleContract);
}
function getOracleContract() public view returns(address) {
return oracleContract;
}
function setTokenContract(address _newTokenContract) public onlyGovernance {
morpherToken = _newTokenContract;
emit TokenChange(_newTokenContract);
}
function getTokenContract() public view returns(address) {
return morpherToken;
}
function setAdministrator(address _newAdministrator) public onlyGovernance {
administrator = _newAdministrator;
emit AdministratorChange(_newAdministrator);
}
function getAdministrator() public view returns(address) {
return administrator;
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for platform operating rewards
// ----------------------------------------------------------------------------
function setRewardAddress(address _newRewardsAddress) public onlyGovernance {
morpherRewards = _newRewardsAddress;
emit RewardsChange(_newRewardsAddress, rewardBasisPoints);
}
function setRewardBasisPoints(uint256 _newRewardBasisPoints) public onlyGovernance {
if (mainChain == true) {
require(_newRewardBasisPoints <= 15000, "MorpherState: Reward basis points need to be less or equal to 15000.");
} else {
require(_newRewardBasisPoints == 0, "MorpherState: Reward basis points can only be set on Ethereum.");
}
rewardBasisPoints = _newRewardBasisPoints;
emit RewardsChange(morpherRewards, _newRewardBasisPoints);
}
function setLastRewardTime(uint256 _lastRewardTime) private {
lastRewardTime = _lastRewardTime;
emit LastRewardTime(_lastRewardTime);
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for platform administration
// ----------------------------------------------------------------------------
function activateMarket(bytes32 _activateMarket) public onlyAdministrator {
marketActive[_activateMarket] = true;
emit MarketActivated(_activateMarket);
}
function deActivateMarket(bytes32 _deActivateMarket) public onlyAdministrator {
marketActive[_deActivateMarket] = false;
emit MarketDeActivated(_deActivateMarket);
}
function getMarketActive(bytes32 _marketId) public view returns(bool _active) {
return marketActive[_marketId];
}
function setMaximumLeverage(uint256 _newMaximumLeverage) public onlyAdministrator {
require(_newMaximumLeverage > PRECISION, "MorpherState: Leverage precision is 1e8");
maximumLeverage = _newMaximumLeverage;
emit MaximumLeverageChange(_newMaximumLeverage);
}
function getMaximumLeverage() public view returns(uint256 _maxLeverage) {
return maximumLeverage;
}
function pauseState() public onlyAdministrator {
paused = true;
emit StatePaused(msg.sender, true);
}
function unPauseState() public onlyAdministrator {
paused = false;
emit StatePaused(msg.sender, false);
}
// ----------------------------------------------------------------------------
// Setter/Getter for side chain state
// ----------------------------------------------------------------------------
function setSideChainMerkleRoot(bytes32 _sideChainMerkleRoot) public onlyBridge {
sideChainMerkleRoot = _sideChainMerkleRoot;
sideChainMerkleRootWrittenAtTime = now;
payOperatingReward();
emit SideChainMerkleRootUpdate(_sideChainMerkleRoot);
}
function getSideChainMerkleRoot() public view returns(bytes32 _sideChainMerkleRoot) {
return sideChainMerkleRoot;
}
function setSideChainOperator(address _address) public onlyAdministrator {
sideChainOperator = _address;
emit NewSideChainOperator(_address);
}
function getSideChainOperator() public view returns (address _address) {
return sideChainOperator;
}
function getSideChainMerkleRootWrittenAtTime() public view returns(uint256 _sideChainMerkleRoot) {
return sideChainMerkleRootWrittenAtTime;
}
// ----------------------------------------------------------------------------
// Setter/Getter functions for portfolio
// ----------------------------------------------------------------------------
function setPosition(
address _address,
bytes32 _marketId,
uint256 _timeStamp,
uint256 _longShares,
uint256 _shortShares,
uint256 _meanEntryPrice,
uint256 _meanEntrySpread,
uint256 _meanEntryLeverage,
uint256 _liquidationPrice
) public onlyPlatform {
portfolio[_address][_marketId].lastUpdated = _timeStamp;
portfolio[_address][_marketId].longShares = _longShares;
portfolio[_address][_marketId].shortShares = _shortShares;
portfolio[_address][_marketId].meanEntryPrice = _meanEntryPrice;
portfolio[_address][_marketId].meanEntrySpread = _meanEntrySpread;
portfolio[_address][_marketId].meanEntryLeverage = _meanEntryLeverage;
portfolio[_address][_marketId].liquidationPrice = _liquidationPrice;
portfolio[_address][_marketId].positionHash = getPositionHash(
_address,
_marketId,
_timeStamp,
_longShares,
_shortShares,
_meanEntryPrice,
_meanEntrySpread,
_meanEntryLeverage,
_liquidationPrice
);
if (_longShares > 0 || _shortShares > 0) {
addExposureByMarket(_marketId, _address);
} else {
deleteExposureByMarket(_marketId, _address);
}
emit SetPosition(
portfolio[_address][_marketId].positionHash,
_address,
_marketId,
_timeStamp,
_longShares,
_shortShares,
_meanEntryPrice,
_meanEntrySpread,
_meanEntryLeverage,
_liquidationPrice
);
}
function getPosition(
address _address,
bytes32 _marketId
) public view returns (
uint256 _longShares,
uint256 _shortShares,
uint256 _meanEntryPrice,
uint256 _meanEntrySpread,
uint256 _meanEntryLeverage,
uint256 _liquidationPrice
) {
return(
portfolio[_address][_marketId].longShares,
portfolio[_address][_marketId].shortShares,
portfolio[_address][_marketId].meanEntryPrice,
portfolio[_address][_marketId].meanEntrySpread,
portfolio[_address][_marketId].meanEntryLeverage,
portfolio[_address][_marketId].liquidationPrice
);
}
function getPositionHash(
address _address,
bytes32 _marketId,
uint256 _timeStamp,
uint256 _longShares,
uint256 _shortShares,
uint256 _meanEntryPrice,
uint256 _meanEntrySpread,
uint256 _meanEntryLeverage,
uint256 _liquidationPrice
) public pure returns (bytes32 _hash) {
return keccak256(
abi.encodePacked(
_address,
_marketId,
_timeStamp,
_longShares,
_shortShares,
_meanEntryPrice,
_meanEntrySpread,
_meanEntryLeverage,
_liquidationPrice
)
);
}
function getBalanceHash(address _address, uint256 _balance) public pure returns (bytes32 _hash) {
return keccak256(abi.encodePacked(_address, _balance));
}
function getLastUpdated(address _address, bytes32 _marketId) public view returns (uint256 _lastUpdated) {
return(portfolio[_address][_marketId].lastUpdated);
}
function getLongShares(address _address, bytes32 _marketId) public view returns (uint256 _longShares) {
return(portfolio[_address][_marketId].longShares);
}
function getShortShares(address _address, bytes32 _marketId) public view returns (uint256 _shortShares) {
return(portfolio[_address][_marketId].shortShares);
}
function getMeanEntryPrice(address _address, bytes32 _marketId) public view returns (uint256 _meanEntryPrice) {
return(portfolio[_address][_marketId].meanEntryPrice);
}
function getMeanEntrySpread(address _address, bytes32 _marketId) public view returns (uint256 _meanEntrySpread) {
return(portfolio[_address][_marketId].meanEntrySpread);
}
function getMeanEntryLeverage(address _address, bytes32 _marketId) public view returns (uint256 _meanEntryLeverage) {
return(portfolio[_address][_marketId].meanEntryLeverage);
}
function getLiquidationPrice(address _address, bytes32 _marketId) public view returns (uint256 _liquidationPrice) {
return(portfolio[_address][_marketId].liquidationPrice);
}
// ----------------------------------------------------------------------------
// Record positions by market by address. Needed for exposure aggregations
// and spits and dividends.
// ----------------------------------------------------------------------------
function addExposureByMarket(bytes32 _symbol, address _address) private {
// Address must not be already recored
uint256 _myExposureIndex = getExposureMappingIndex(_symbol, _address);
if (_myExposureIndex == 0) {
uint256 _maxMappingIndex = getMaxMappingIndex(_symbol).add(1);
setMaxMappingIndex(_symbol, _maxMappingIndex);
setExposureMapping(_symbol, _address, _maxMappingIndex);
}
}
function deleteExposureByMarket(bytes32 _symbol, address _address) private {
// Get my index in mapping
uint256 _myExposureIndex = getExposureMappingIndex(_symbol, _address);
// Get last element of mapping
uint256 _lastIndex = getMaxMappingIndex(_symbol);
address _lastAddress = getExposureMappingAddress(_symbol, _lastIndex);
// If _myExposureIndex is greater than 0 (i.e. there is an exposure of that address on that market) delete it
if (_myExposureIndex > 0) {
// If _myExposureIndex is less than _lastIndex overwrite element at _myExposureIndex with element at _lastIndex in
// deleted elements position.
if (_myExposureIndex < _lastIndex) {
setExposureMappingAddress(_symbol, _lastAddress, _myExposureIndex);
setExposureMappingIndex(_symbol, _lastAddress, _myExposureIndex);
}
// Delete _lastIndex and _lastAddress element and reduce maxExposureIndex
setExposureMappingAddress(_symbol, address(0), _lastIndex);
setExposureMappingIndex(_symbol, _address, 0);
// Shouldn't happen, but check that not empty
if (_lastIndex > 0) {
setMaxMappingIndex(_symbol, _lastIndex.sub(1));
}
}
}
// ----------------------------------------------------------------------------
// Calculate and send operating reward
// Every 24 hours the protocol mints rewardBasisPoints/(PRECISION) percent of the total
// supply as reward for the protocol operator. The amount can not exceed 0.015% per
// day.
// ----------------------------------------------------------------------------
function payOperatingReward() public onlyMainChain {
if (now > lastRewardTime.add(REWARDPERIOD)) {
uint256 _reward = totalSupply.mul(rewardBasisPoints).div(PRECISION);
setLastRewardTime(lastRewardTime.add(REWARDPERIOD));
mint(morpherRewards, _reward);
emit OperatingRewardMinted(morpherRewards, _reward);
}
}
}
pragma solidity 0.5.16;
import "./IERC20.sol";
import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20Mintable}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract MorpherToken is IERC20, Ownable {
MorpherState state;
using SafeMath for uint256;
string public constant name = "Morpher";
string public constant symbol = "MPH";
uint8 public constant decimals = 18;
modifier onlyState {
require(msg.sender == address(state), "ERC20: caller must be MorpherState contract.");
_;
}
modifier canTransfer {
require(state.getCanTransfer(msg.sender), "ERC20: token transfers disabled on sidechain.");
_;
}
event LinkState(address _address);
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
setMorpherState(_stateAddress);
transferOwnership(_coldStorageOwnerAddress);
}
// ------------------------------------------------------------------------
// Links Token Contract with State
// ------------------------------------------------------------------------
function setMorpherState(address _stateAddress) public onlyOwner {
state = MorpherState(_stateAddress);
emit LinkState(_stateAddress);
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view returns (uint256) {
return state.totalSupply();
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address _account) public view returns (uint256) {
return state.balanceOf(_account);
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*
* Emits a {Transfer} event via emitTransfer called by MorpherState
*/
function transfer(address _recipient, uint256 _amount) public returns (bool) {
_transfer(msg.sender, _recipient, _amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address _owner, address _spender) public view returns (uint256) {
return state.getAllowance(_owner, _spender);
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address _spender, uint256 _amount) public returns (bool) {
_approve(msg.sender, _spender, _amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20};
*
* Requirements:
* - `_sender` and `_recipient` cannot be the zero address.
* - `_sender` must have a balance of at least `amount`.
* - the caller must have allowance for `_sender`'s tokens of at least
* `amount`.
*/
function transferFrom(address _sender, address _recipient, uint256 amount) public returns (bool) {
_transfer(_sender, _recipient, amount);
_approve(_sender, msg.sender, state.getAllowance(_sender, msg.sender).sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `_spender` cannot be the zero address.
*/
function increaseAllowance(address _spender, uint256 _addedValue) public returns (bool) {
_approve(msg.sender, _spender, state.getAllowance(msg.sender, _spender).add(_addedValue));
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address _spender, uint256 _subtractedValue) public returns (bool) {
_approve(msg.sender, _spender, state.getAllowance(msg.sender, _spender).sub(_subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
/**
* @dev Caller destroys `_amount` tokens permanently
*
* Emits a {Transfer} event to zero address called by MorpherState via emitTransfer.
*
* Requirements:
*
* - Caller must have token balance of at least `_amount`
*
*/
function burn(uint256 _amount) public returns (bool) {
state.burn(msg.sender, _amount);
return true;
}
/**
* @dev Emits a {Transfer} event
*
* MorpherState emits a {Transfer} event.
*
* Requirements:
*
* - Caller must be MorpherState
*
*/
function emitTransfer(address _from, address _to, uint256 _amount) public onlyState {
emit Transfer(_from, _to, _amount);
}
/**
* @dev Moves tokens `_amount` from `sender` to `_recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event via emitTransfer called by MorpherState
*
* Requirements:
*
* - `_sender` cannot be the zero address.
* - `_recipient` cannot be the zero address.
* - `_sender` must have a balance of at least `_amount`.
*/
function _transfer(address _sender, address _recipient, uint256 _amount) canTransfer internal {
require(_sender != address(0), "ERC20: transfer from the zero address");
require(_recipient != address(0), "ERC20: transfer to the zero address");
require(state.balanceOf(_sender) >= _amount, "ERC20: transfer amount exceeds balance");
state.transfer(_sender, _recipient, _amount);
}
/**
* @dev Sets `_amount` as the allowance of `spender` over the `owner`s tokens.
*
* This is internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address _owner, address _spender, uint256 _amount) internal {
require(_owner != address(0), "ERC20: approve from the zero address");
require(_spender != address(0), "ERC20: approve to the zero address");
state.setAllowance(_owner, _spender, _amount);
emit Approval(_owner, _spender, _amount);
}
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function () external payable {
revert("ERC20: You can't deposit Ether here");
}
}
pragma solidity 0.5.16;
import "./IERC20.sol";
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor () internal {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @return the address of the owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller should be owner.");
_;
}
/**
* @return true if `msg.sender` is the owner of the contract.
*/
function isOwner() public view returns (bool) {
return msg.sender == _owner;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
* @notice Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: use renounce ownership instead.");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
// ------------------------------------------------------------------------
// Owner can transfer out any accidentally sent ERC20 tokens
// ------------------------------------------------------------------------
function transferAnyERC20Token(address _tokenAddress, uint256 _tokens) public onlyOwner returns (bool _success) {
return IERC20(_tokenAddress).transfer(owner(), _tokens);
}
}
pragma solidity 0.5.16;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @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) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @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 sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @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) {
// 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 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts 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.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts 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 mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message 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.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_stateAddress","type":"address"},{"internalType":"address","name":"_coldStorageOwnerAddress","type":"address"},{"internalType":"address","name":"_stakingContractAddress","type":"address"},{"internalType":"bool","name":"_escrowOpenOrderEnabled","type":"bool"},{"internalType":"uint256","name":"_deployedTimestampOverride","type":"uint256"},{"internalType":"address","name":"_mintingLimiterAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_mintingLimiterAddress","type":"address"}],"name":"LinkMintingLimiter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_stakingAddress","type":"address"}],"name":"LinkStaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"}],"name":"LinkState","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"}],"name":"LockedPriceForClosingPositions","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_address","type":"address"}],"name":"OrderCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_address","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_closeSharesAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_openMPHTokenAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_tradeDirection","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_orderLeverage","type":"uint256"}],"name":"OrderIdRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_liquidationTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLongShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newShortShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAverageEntry","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAverageSpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAverageLeverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"name":"OrderProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_address","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"_longPosition","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_marketSpread","type":"uint256"}],"name":"PositionLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_userId","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLongShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newShortShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMeanEntryPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMeanEntrySpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMeanEntryLeverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLiquidationPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_mint","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_burn","type":"uint256"}],"name":"PositionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimestamp","type":"uint256"}],"name":"ResetTimestampInOrder","type":"event"},{"constant":true,"inputs":[],"name":"_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_averagePrice","type":"uint256"},{"internalType":"uint256","name":"_averageLeverage","type":"uint256"},{"internalType":"uint256","name":"_positionTimeStampInMs","type":"uint256"}],"name":"calculateMarginInterest","outputs":[{"internalType":"uint256","name":"_marginInterest","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"}],"name":"cancelOrder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"closedMarketPriceLock","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"}],"name":"computeLiquidationPrice","outputs":[{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"deployedTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"escrowOpenOrderAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"escrowOpenOrderEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAdministrator","outputs":[{"internalType":"address","name":"_administrator","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getDeactivatedMarketPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_newMeanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_newMeanEntryLeverage","type":"uint256"},{"internalType":"bool","name":"_long","type":"bool"},{"internalType":"uint256","name":"_positionTimestampInMs","type":"uint256"}],"name":"getLiquidationPrice","outputs":[{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"}],"name":"getOrder","outputs":[{"internalType":"address","name":"_userId","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_closeSharesAmount","type":"uint256"},{"internalType":"uint256","name":"_openMPHTokenAmount","type":"uint256"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getPosition","outputs":[{"internalType":"uint256","name":"_positionLongShares","type":"uint256"},{"internalType":"uint256","name":"_positionShortShares","type":"uint256"},{"internalType":"uint256","name":"_positionAveragePrice","type":"uint256"},{"internalType":"uint256","name":"_positionAverageSpread","type":"uint256"},{"internalType":"uint256","name":"_positionAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastOrderId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_positionAveragePrice","type":"uint256"},{"internalType":"uint256","name":"_positionAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_positionTimeStampInMs","type":"uint256"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"},{"internalType":"bool","name":"_sell","type":"bool"}],"name":"longShareValue","outputs":[{"internalType":"uint256","name":"_shareValue","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"orderNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_liquidationTimestamp","type":"uint256"},{"internalType":"uint256","name":"_timeStampInMS","type":"uint256"}],"name":"processOrder","outputs":[{"internalType":"uint256","name":"_newLongShares","type":"uint256"},{"internalType":"uint256","name":"_newShortShares","type":"uint256"},{"internalType":"uint256","name":"_newAverageEntry","type":"uint256"},{"internalType":"uint256","name":"_newAverageSpread","type":"uint256"},{"internalType":"uint256","name":"_newAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_closeSharesAmount","type":"uint256"},{"internalType":"uint256","name":"_openMPHTokenAmount","type":"uint256"},{"internalType":"bool","name":"_tradeDirection","type":"bool"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"}],"name":"requestOrderId","outputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setDeactivatedMarketPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"setEscrowOpenOrderEnabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_mintingLimiterAddress","type":"address"}],"name":"setMorpherMintingLimiter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_stakingAddress","type":"address"}],"name":"setMorpherStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_stateAddress","type":"address"}],"name":"setMorpherState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_positionAveragePrice","type":"uint256"},{"internalType":"uint256","name":"_positionAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_positionTimeStampInMs","type":"uint256"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"},{"internalType":"bool","name":"_sell","type":"bool"}],"name":"shortShareValue","outputs":[{"internalType":"uint256","name":"_shareValue","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052600780546001600160a01b0319908116731111111111111111111111111111111111111111179091556008805490911660011790553480156200004657600080fd5b506040516200609438038062006094833981810160405260c08110156200006c57600080fd5b50805160208201516040808401516060850151608086015160a090960151600080546001600160a01b031916331780825594519697959693959294929391926001600160a01b03169160008051602062006054833981519152908290a3620000dd866001600160e01b036200014f16565b620000f1846001600160e01b03620001f716565b62000105816001600160e01b036200029f16565b62000119856001600160e01b036200034716565b6007805460ff60a01b1916600160a01b85151502179055816200013d57426200013f565b815b6006555062000454945050505050565b620001626001600160e01b03620003b216565b620001a3576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f978c711532bae8c58f353b0f3c7f3a0dfe600d9ae9a81818f2ad2919b88e19909181900360200190a150565b6200020a6001600160e01b03620003b216565b6200024b576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4016bbc93bb2adf11f6d1b2509a1ab5f593cbe26e54875655329f9c80117f0849181900360200190a150565b620002b26001600160e01b03620003b216565b620002f3576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b600380546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f42c6bffb0e058cc1dfabd910037516fb01b87949d9a476876ff43179d62f4dc89181900360200190a150565b6200035a6001600160e01b03620003b216565b6200039b576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b620003af816001600160e01b03620003c316565b50565b6000546001600160a01b0316331490565b6001600160a01b0381166200040a5760405162461bcd60e51b81526004018080602001828103825260288152602001806200602c6028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216916000805160206200605483398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b615bc880620004646000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063715018a611610104578063ac8f6f7f116100a2578063daf9502711610071578063daf9502714610575578063dc39d06d1461059b578063f2fde38b146105c7578063f40b7b32146105ed576101cf565b8063ac8f6f7f146104dc578063ac9eee2814610522578063b2bdfa7b14610541578063d61aed7a14610549576101cf565b806380104668116100de57806380104668146104895780638da5cb5b146104af5780638f32d59b146104b7578063a386fb56146104bf576101cf565b8063715018a61461042a5780637993a991146104325780637dffd04014610458576101cf565b80634702513c116101715780635778472a1161014b5780635778472a146103755780636950baa8146103d45780636b4f7065146103dc5780637023b78314610405576101cf565b80634702513c1461030d578063480ee2071461032a5780635662ecc71461036d576101cf565b806316f77a5b116101ad57806316f77a5b1461027357806316f8de89146102a857806323aab432146102c25780633754c565146102ca576101cf565b80630fa8f516146101d457806316194bac14610233578063169674071461024f575b600080fd5b610200600480360360408110156101ea57600080fd5b506001600160a01b0381351690602001356105f5565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b61023b610942565b604080519115158252519081900360200190f35b610257610952565b604080516001600160a01b039092168252519081900360200190f35b610200600480360360a081101561028957600080fd5b50803590602081013590604081013590606081013590608001356109c8565b6102b0611176565b60408051918252519081900360200190f35b61025761117c565b6102b0600480360360e08110156102e057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c00135151561118b565b6102b06004803603602081101561032357600080fd5b50356112c1565b6102b0600480360360e081101561034057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c001351515611389565b6102b061140c565b6103926004803603602081101561038b57600080fd5b5035611412565b604080516001600160a01b0390981688526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b610257611459565b6102b0600480360360608110156103f257600080fd5b5080359060208101359060400135611468565b6104286004803603604081101561041b57600080fd5b50803590602001356115a5565b005b610428611765565b6104286004803603602081101561044857600080fd5b50356001600160a01b03166117f6565b6102b06004803603608081101561046e57600080fd5b50803590602081013590604081013515159060600135611891565b6104286004803603602081101561049f57600080fd5b50356001600160a01b031661192b565b6102576119c6565b61023b6119d5565b6102b0600480360360208110156104d557600080fd5b50356119e6565b6102b0600480360360c08110156104f257600080fd5b506001600160a01b0381351690602081013590604081013590606081013590608081013515159060a00135611a75565b6104286004803603602081101561053857600080fd5b50351515612226565b61025761228b565b6104286004803603604081101561055f57600080fd5b50803590602001356001600160a01b031661229a565b6104286004803603602081101561058b57600080fd5b50356001600160a01b0316612517565b61023b600480360360408110156105b157600080fd5b506001600160a01b0381351690602001356125b2565b610428600480360360208110156105dd57600080fd5b50356001600160a01b0316612697565b6102b06126ea565b600154604080516377afd19160e11b81526001600160a01b03858116600483015260248201859052915160009384938493849384938493169163ef5fa322916044808301926020929190829003018186803b15801561065357600080fd5b505afa158015610667573d6000803e3d6000fd5b505050506040513d602081101561067d57600080fd5b5051600154604080516301864ba360e41b81526001600160a01b038c81166004830152602482018c905291519190921691631864ba30916044808301926020929190829003018186803b1580156106d357600080fd5b505afa1580156106e7573d6000803e3d6000fd5b505050506040513d60208110156106fd57600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038d81166004830152602482018d90529151919092169163e291f135916044808301926020929190829003018186803b15801561075357600080fd5b505afa158015610767573d6000803e3d6000fd5b505050506040513d602081101561077d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038e81166004830152602482018e90529151919092169163efeecb04916044808301926020929190829003018186803b1580156107d357600080fd5b505afa1580156107e7573d6000803e3d6000fd5b505050506040513d60208110156107fd57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038f81166004830152602482018f90529151919092169163faddee14916044808301926020929190829003018186803b15801561085357600080fd5b505afa158015610867573d6000803e3d6000fd5b505050506040513d602081101561087d57600080fd5b8101908080519060200190929190505050600160009054906101000a90046001600160a01b03166001600160a01b031663652f17638e8e6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b15801561090157600080fd5b505afa158015610915573d6000803e3d6000fd5b505050506040513d602081101561092b57600080fd5b5051949d939c50919a509850965090945092505050565b600754600160a01b900460ff1681565b60015460408051631696740760e01b815290516000926001600160a01b0316916316967407916004808301926020929190829003018186803b15801561099757600080fd5b505afa1580156109ab573d6000803e3d6000fd5b505050506040513d60208110156109c157600080fd5b5051905090565b600080600080600080600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1f57600080fd5b505afa158015610a33573d6000803e3d6000fd5b505050506040513d6020811015610a4957600080fd5b50516001600160a01b03163314610a915760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b60008b8152600960205260409020546001600160a01b0316610ae45760405162461bcd60e51b815260040180806020018281038252603e815260200180615919603e913960400191505060405180910390fd5b60008a11610b235760405162461bcd60e51b8152600401808060200182810382526049815260200180615b046049913960600191505060405180910390fd5b888a1015610b625760405162461bcd60e51b81526004018080602001828103825260558152602001806159c26055913960600191505060405180910390fd5b60008b815260096020818152604092839020600681018e9055600781018d90559182018a9055600582018b9055600180549201548351634a4cce9760e01b8152600481019190915292516001600160a01b0390921692634a4cce979260248083019392829003018186803b158015610bd957600080fd5b505afa158015610bed573d6000803e3d6000fd5b505050506040513d6020811015610c0357600080fd5b5051610c4057610c128b6126f0565b60008b815260096020526040902060010154610c2d906119e6565b60008c8152600960205260409020600601555b6001805460008d81526009602090815260409182902080549401548251630f5fd3cf60e21b81526001600160a01b039586166004820152602481019190915291519390921692633d7f4f3c92604480840193919291829003018186803b158015610ca957600080fd5b505afa158015610cbd573d6000803e3d6000fd5b505050506040513d6020811015610cd357600080fd5b5051881115610ce557610ce58b61272e565b610cee8b612c41565b60008b81526009602052604090206004015460ff1615610d1657610d118b612cea565b610d1f565b610d1f8b612fe0565b60008b815260096020818152604080842080546001820180546001600160a01b03198316845590879055600283018790556003830187905560048301805460ff1916905560058301879055600683018790556007830187905560088301879055948201869055600a8201869055600b8201869055600c8201869055600d8201869055600e8201869055600f82018690556010820186905560118201869055601282018690556013820186905560149091019490945580518f81529182018e90528181018d9052606082018c9052608082018b905260a082018a905260c0820189905260e08201889052610100820187905261012082018690526101408201859052516001600160a01b03909316927f696a3d28d7b4bcfc9cbfef719a03218d7a502cda20d01f9ef8086249e8165492918190036101600190a1600154604080516377afd19160e11b81526001600160a01b038581166004830152602482018590529151919092169163ef5fa322916044808301926020929190829003018186803b158015610eac57600080fd5b505afa158015610ec0573d6000803e3d6000fd5b505050506040513d6020811015610ed657600080fd5b5051600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291519190921691631864ba30916044808301926020929190829003018186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d6020811015610f5657600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038781166004830152602482018790529151919092169163e291f135916044808301926020929190829003018186803b158015610fac57600080fd5b505afa158015610fc0573d6000803e3d6000fd5b505050506040513d6020811015610fd657600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038881166004830152602482018890529151919092169163efeecb04916044808301926020929190829003018186803b15801561102c57600080fd5b505afa158015611040573d6000803e3d6000fd5b505050506040513d602081101561105657600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038981166004830152602482018990529151919092169163faddee14916044808301926020929190829003018186803b1580156110ac57600080fd5b505afa1580156110c0573d6000803e3d6000fd5b505050506040513d60208110156110d657600080fd5b50516001546040805163652f176360e01b81526001600160a01b038a81166004830152602482018a90529151919092169163652f1763916044808301926020929190829003018186803b15801561112c57600080fd5b505afa158015611140573d6000803e3d6000fd5b505050506040513d602081101561115657600080fd5b5051949c50929a5090985096509450925050509550955095509550955095565b60045481565b6008546001600160a01b031681565b600087876305f5e1008110156111a257506305f5e1005b836111ad5750859050835b866111bb838360008c611891565b116111c957600092506112b4565b6111fd6305f5e1006111f16111e4828563ffffffff6132b816565b859063ffffffff61331916565b9063ffffffff61337216565b925061122761121a6305f5e1006111f18a8563ffffffff61331916565b849063ffffffff6133b416565b9250600184151514156112895761124f61121a6305f5e1006111f1898563ffffffff61331916565b9250600061125e83838b611468565b905083811161127e57611277848263ffffffff6133b416565b9350611283565b600093505b506112b4565b6112b16112a46305f5e1006111f1898963ffffffff61331916565b849063ffffffff6132b816565b92505b5050979650505050505050565b600081815260096020526040812060138101829055600e01541561132057600082815260096020819052604090912060108101546012820154919092015461130d929190600190611891565b6000838152600960205260409020601301555b6000828152600960205260409020600f01541561137357600082815260096020819052604082206010810154601282015491909201546113609390611891565b6000838152600960205260409020601301555b5060009081526009602052604090206013015490565b600087876305f5e1008110156113a057506305f5e1005b836113ab5750859050835b6113b8828260018b611891565b87116113c757600092506112b4565b6113e26305f5e1006111f16111e4848363ffffffff6133b416565b9250611227836114006305f5e1006111f18b8663ffffffff61331916565b9063ffffffff6133b416565b60055481565b60009081526009602052604090208054600182015460028301546003840154600685015460078601546008909601546001600160a01b039095169693959294919390929190565b6007546001600160a01b031681565b600654600090611480836103e863ffffffff61337216565b101561149e5760065461149b906103e863ffffffff61331916565b91505b6114b56111e4846305f5e10063ffffffff6133b416565b90506115016114f460016114e8620151806111f16114db886103e863ffffffff61337216565b429063ffffffff6133b416565b9063ffffffff6132b816565b829063ffffffff61331916565b905061159d6305f5e1006111f16305f5e1006111f1600260009054906101000a90046001600160a01b03166001600160a01b0316637c3a00fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561156457600080fd5b505afa158015611578573d6000803e3d6000fd5b505050506040513d602081101561158e57600080fd5b5051869063ffffffff61331916565b949350505050565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f357600080fd5b505afa158015611607573d6000803e3d6000fd5b505050506040513d602081101561161d57600080fd5b50516001600160a01b031633146116655760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6001546008546001600160a01b039182169163be7e64b6911684611691426103e863ffffffff61331916565b604080516001600160e01b031960e087901b1681526001600160a01b039094166004850152602484019290925260448301526000606483018190526084830181905260a4830186905260c4830181905260e48301819052610104830181905290516101248084019382900301818387803b15801561170e57600080fd5b505af1158015611722573d6000803e3d6000fd5b5050604080518581526020810185905281517f3cf30f15febef0d3f8e86318070db2c80d03fd14e8406d326aab41cb043f18399450908190039091019150a15050565b61176d6119d5565b6117ac576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6117fe6119d5565b61183d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4016bbc93bb2adf11f6d1b2509a1ab5f593cbe26e54875655329f9c80117f0849181900360200190a150565b6000600183151514156118ea576118c6846111f16118b9826305f5e10063ffffffff6133b416565b889063ffffffff61331916565b90506118e36118d6868685611468565b829063ffffffff6132b816565b905061159d565b611905846111f16118b9826305f5e10063ffffffff6132b816565b9050611922611915868685611468565b829063ffffffff6133b416565b95945050505050565b6119336119d5565b611972576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f978c711532bae8c58f353b0f3c7f3a0dfe600d9ae9a81818f2ad2919b88e19909181900360200190a150565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600154600854604080516307d47a8b60e11b81526001600160a01b03928316600482015260248101859052905160009384931691630fa8f5169160448083019260c0929190829003018186803b158015611a3f57600080fd5b505afa158015611a53573d6000803e3d6000fd5b505050506040513d60c0811015611a6957600080fd5b50604001519392505050565b6001546040805163e3bbb56560e01b815290516000926001600160a01b03169163e3bbb565916004808301926020929190829003018186803b158015611aba57600080fd5b505afa158015611ace573d6000803e3d6000fd5b505050506040513d6020811015611ae457600080fd5b50516001600160a01b03163314611b2c5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6305f5e100821015611b6f5760405162461bcd60e51b8152600401808060200182810382526041815260200180615ac36041913960600191505060405180910390fd5b600160009054906101000a90046001600160a01b03166001600160a01b0316637c995e916040518163ffffffff1660e01b815260040160206040518083038186803b158015611bbd57600080fd5b505afa158015611bd1573d6000803e3d6000fd5b505050506040513d6020811015611be757600080fd5b5051821115611c275760405162461bcd60e51b815260040180806020018281038252603e815260200180615752603e913960400191505060405180910390fd5b611c3487878787876133f6565b600160009054906101000a90046001600160a01b03166001600160a01b031663755ca87a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8257600080fd5b505afa158015611c96573d6000803e3d6000fd5b505050506040513d6020811015611cac57600080fd5b505160015460408051631722e4cd60e21b81526001600160a01b038b8116600483015291519190921691635c8b9334916024808301926020929190829003018186803b158015611cfb57600080fd5b505afa158015611d0f573d6000803e3d6000fd5b505050506040513d6020811015611d2557600080fd5b5051111580611dad5750600154604080516330826beb60e21b81526001600160a01b038a8116600483015291514393929092169163c209afac91602480820192602092909190829003018186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d6020811015611da957600080fd5b5051105b611de85760405162461bcd60e51b815260040180806020018281038252604a815260200180615839604a913960600191505060405180910390fd5b8315611f73578215611eb657600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a905291519190921691631864ba30916044808301926020929190829003018186803b158015611e4857600080fd5b505afa158015611e5c573d6000803e3d6000fd5b505050506040513d6020811015611e7257600080fd5b50518514611eb15760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b611f73565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529151919092169163ef5fa322916044808301926020929190829003018186803b158015611f0a57600080fd5b505afa158015611f1e573d6000803e3d6000fd5b505050506040513d6020811015611f3457600080fd5b50518514611f735760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b600154604080516303d4880760e11b81526001600160a01b038a81166004830152915191909216916307a9100e91602480830192600092919082900301818387803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b505060015460408051635e61f1a160e11b81526001600160a01b038c81166004830152915191909216935063bcc3e3429250602480830192600092919082900301818387803b15801561202757600080fd5b505af115801561203b573d6000803e3d6000fd5b505050506004600081548092919060010191905055508643878787878760045460405160200180896001600160a01b03166001600160a01b031660601b8152601401888152602001878152602001868152602001858152602001841515151560f81b81526001018381526020018281526020019850505050505050505060405160208183030381529060405280519060200120905080600581905550866009600083815260200190815260200160002060000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550856009600083815260200190815260200160002060010181905550846009600083815260200190815260200160002060020181905550836009600083815260200190815260200160002060030181905550826009600083815260200190815260200160002060040160006101000a81548160ff02191690831515021790555081600960008381526020019081526020016000206008018190555085876001600160a01b03167fd5dec9e768ba83c154ee9ecf7a0c145c8e7ee75e1cc4af2d271a1f9c93bb3946838888888860405180868152602001858152602001848152602001831515151581526020018281526020019550505050505060405180910390a361221c8185613703565b9695505050505050565b61222e6119d5565b61226d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b60078054911515600160a01b0260ff60a01b19909216919091179055565b6000546001600160a01b031681565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156122e857600080fd5b505afa1580156122fc573d6000803e3d6000fd5b505050506040513d602081101561231257600080fd5b50516001600160a01b0316331461235a5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b038281169116148061239a5750612385610952565b6001600160a01b0316816001600160a01b0316145b6123d55760405162461bcd60e51b815260040180806020018281038252604381526020018061597f6043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b03166124285760405162461bcd60e51b815260040180806020018281038252603c815260200180615883603c913960400191505060405180910390fd5b61243182612c41565b600082815260096020819052604080832080546001600160a01b031916815560018101849055600281018490556003810184905560048101805460ff1916905560058101849055600681018490556007810184905560088101849055918201839055600a8201839055600b8201839055600c8201839055600d8201839055600e8201839055600f8201839055601082018390556011820183905560128201839055601382018390556014909101829055516001600160a01b0383169184917fa6eb7cdc219e1518ced964e9a34e61d68a94e4f1569db3e84256ba981ba527539190a35050565b61251f6119d5565b61255e576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600380546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f42c6bffb0e058cc1dfabd910037516fb01b87949d9a476876ff43179d62f4dc89181900360200190a150565b60006125bc6119d5565b6125fb576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6126126119c6565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561266257600080fd5b505af1158015612676573d6000803e3d6000fd5b505050506040513d602081101561268c57600080fd5b505190505b92915050565b61269f6119d5565b6126de576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b6126e7816137bc565b50565b60065481565b600081815260096020526040902080546001820154600283015460038401546004909401546126e7946001600160a01b03909416939060ff166133f6565b600081815260096020908152604091829020805460018083015460059093015490548551630f5fd3cf60e21b81526001600160a01b0393841660048201819052602482018690529651949592949190931692633d7f4f3c926044808301939192829003018186803b1580156127a257600080fd5b505afa1580156127b6573d6000803e3d6000fd5b505050506040513d60208110156127cc57600080fd5b5051811115612c3b57600154604080516377afd19160e11b81526001600160a01b038681166004830152602482018690529151600093929092169163ef5fa32291604480820192602092909190829003018186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d602081101561285757600080fd5b50511115612a0a5760015460008581526009602081815260408084209092015482516301864ba360e41b81526001600160a01b038981166004830152602482018990529351939095169463be7e64b6948994899491928892631864ba3092604480840193829003018186803b1580156128cf57600080fd5b505afa1580156128e3573d6000803e3d6000fd5b505050506040513d60208110156128f957600080fd5b5051604080516001600160e01b031960e089901b1681526001600160a01b0390961660048701526024860194909452604485019290925260648401526084830152600060a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b15801561297a57600080fd5b505af115801561298e573d6000803e3d6000fd5b5050506000858152600960208181526040928390209182015460068301546007909301548451600181529283019190915281840192909252606081019190915290518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291516000939290921691631864ba3091604480820192602092909190829003018186803b158015612a6257600080fd5b505afa158015612a76573d6000803e3d6000fd5b505050506040513d6020811015612a8c57600080fd5b50511115612c3b576001546000858152600960208181526040928390209091015482516377afd19160e11b81526001600160a01b038881166004830152602482018890529351939094169363be7e64b6938893889392879263ef5fa32292604480840193919291829003018186803b158015612b0757600080fd5b505afa158015612b1b573d6000803e3d6000fd5b505050506040513d6020811015612b3157600080fd5b5051604080516001600160e01b031960e088901b1681526001600160a01b03909516600486015260248501939093526044840191909152606483015260006084830181905260a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b158015612bb457600080fd5b505af1158015612bc8573d6000803e3d6000fd5b5050506000858152600960208181526040808420928301546006840154600790940154825195865292850152838101929092526060830152518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b50505050565b600081815260096020526040902060140154156126e75760008181526009602052604080822060148101805490849055600154600754925484516317d5759960e31b81526001600160a01b0394851660048201529084166024820152604481018390529351919492169263beabacc892606480830193919282900301818387803b158015612cce57600080fd5b505af1158015612ce2573d6000803e3d6000fd5b505050505050565b60008181526009602052604090206002015415612e735760018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612d6a57600080fd5b505afa158015612d7e573d6000803e3d6000fd5b505050506040513d6020811015612d9457600080fd5b505160008281526009602052604090206002015411612dcb5760008181526009602052604090206002810154600b90910155612e73565b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612e3457600080fd5b505afa158015612e48573d6000803e3d6000fd5b505050506040513d6020811015612e5e57600080fd5b50516000828152600960205260409020600b01555b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612edc57600080fd5b505afa158015612ef0573d6000803e3d6000fd5b505050506040513d6020811015612f0657600080fd5b50516000828152600960205260409020600b0154148015612f37575060008181526009602052604090206003015415155b15612fa057600081815260096020526040812060068101546008820154600790920154612f8d93612f6f939142918491908490611389565b6000838152600960205260409020600301549063ffffffff61337216565b6000828152600960205260409020600a01555b6000818152600960205260409020600b015415612fc057612fc08161385c565b6000818152600960205260409020600a0154156126e7576126e781613c45565b600081815260096020526040902060020154156131695760018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561306057600080fd5b505afa158015613074573d6000803e3d6000fd5b505050506040513d602081101561308a57600080fd5b5051600082815260096020526040902060020154116130c15760008181526009602052604090206002810154600a90910155613169565b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561312a57600080fd5b505afa15801561313e573d6000803e3d6000fd5b505050506040513d602081101561315457600080fd5b50516000828152600960205260409020600a01555b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b1580156131d257600080fd5b505afa1580156131e6573d6000803e3d6000fd5b505050506040513d60208110156131fc57600080fd5b50516000828152600960205260409020600a015414801561322d575060008181526009602052604090206003015415155b156132785760008181526009602052604081206006810154600882015460079092015461326593612f6f93914291849190849061118b565b6000828152600960205260409020600b01555b6000818152600960205260409020600a0154156132985761329881614304565b6000818152600960205260409020600b0154156126e7576126e7816146a0565b600082820183811015613312576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008261332857506000612691565b8282028284828161333557fe5b04146133125760405162461bcd60e51b8152600401808060200182810382526021815260200180615a176021913960400191505060405180910390fd5b600061331283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614c3b565b600061331283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614cdd565b81156134b95760015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561344857600080fd5b505afa15801561345c573d6000803e3d6000fd5b505050506040513d602081101561347257600080fd5b505115156001146134b45760405162461bcd60e51b8152600401808060200182810382526048815260200180615a7b6048913960600191505060405180910390fd5b6136fc565b60015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561350557600080fd5b505afa158015613519573d6000803e3d6000fd5b505050506040513d602081101561352f57600080fd5b50516136fc576000613540856119e6565b1161357c5760405162461bcd60e51b815260040180806020018281038252605a8152602001806158bf605a913960600191505060405180910390fd5b801561363f57600154604080516301864ba360e41b81526001600160a01b0388811660048301526024820188905291519190921691631864ba30916044808301926020929190829003018186803b1580156135d657600080fd5b505afa1580156135ea573d6000803e3d6000fd5b505050506040513d602081101561360057600080fd5b505183146134b45760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151919092169163ef5fa322916044808301926020929190829003018186803b15801561369357600080fd5b505afa1580156136a7573d6000803e3d6000fd5b505050506040513d60208110156136bd57600080fd5b505183146136fc5760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b5050505050565b600754600160a01b900460ff16801561371c5750600081115b156137b8576001546000838152600960205260408082205460075482516317d5759960e31b81526001600160a01b039283166004820152908216602482015260448101869052915193169263beabacc89260648084019391929182900301818387803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b5050506000838152600960205260409020601401829055505b5050565b6001600160a01b0381166138015760405162461bcd60e51b81526004018080602001828103825260288152602001806159576028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008181526009602090815260408083208054600180830154600b90930154905484516301864ba360e41b81526001600160a01b0393841660048201819052602482018690529551959794969495869586958695613914959094911692631864ba3092604480840193919291829003018186803b1580156138dc57600080fd5b505afa1580156138f0573d6000803e3d6000fd5b505050506040513d602081101561390657600080fd5b50519063ffffffff6133b416565b9050600061392188614d37565b600154604080516301864ba360e41b81526001600160a01b038b81166004830152602482018b90529151939450911691631864ba3091604480820192602092909190829003018186803b15801561397757600080fd5b505afa15801561398b573d6000803e3d6000fd5b505050506040513d60208110156139a157600080fd5b50516000898152600960205260409020600b015414156139cf5760009450600093506305f5e1009250613b5e565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193985091169163efeecb0491604480820192602092909190829003018186803b158015613aa557600080fd5b505afa158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193975091169163faddee1491604480820192602092909190829003018186803b158015613b2757600080fd5b505afa158015613b3b573d6000803e3d6000fd5b505050506040513d6020811015613b5157600080fd5b50519250613b5e886151f4565b6000888152600960209081526040808320600c810193909355600d8301849055600180548454919094015482516377afd19160e11b81526001600160a01b0392831660048201526024810191909152915193169263ef5fa32292604480840193919291829003018186803b158015613bd557600080fd5b505afa158015613be9573d6000803e3d6000fd5b505050506040513d6020811015613bff57600080fd5b50516000898152600960205260409020600e810191909155600f81018390556010810186905560118101859055601201839055613c3b886152fe565b5050505050505050565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b158015613cb657600080fd5b505afa158015613cca573d6000803e3d6000fd5b505050506040513d6020811015613ce057600080fd5b505190506305f5e100811015613cf757506305f5e1005b613d0b816305f5e10063ffffffff6133b416565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b90529451959650613db59592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b505afa158015613d90573d6000803e3d6000fd5b505050506040513d6020811015613da657600080fd5b5051849063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b158015613e0e57600080fd5b505afa158015613e22573d6000803e3d6000fd5b505050506040513d6020811015613e3857600080fd5b50511115613e9e5760015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151613e97938593169163faddee14916044808301926020929190829003018186803b1580156138dc57600080fd5b9050613ea2565b5060005b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151600093613f40936305f5e100936111f193919092169163ef5fa322916044808301926020929190829003018186803b158015613f0757600080fd5b505afa158015613f1b573d6000803e3d6000fd5b505050506040513d6020811015613f3157600080fd5b5051859063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a90529151939450613fd6938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b505afa158015613fb2573d6000803e3d6000fd5b505050506040513d6020811015613fc857600080fd5b50519063ffffffff61331916565b6000888152600960205260409020600a810154600890910154919450614005916112a49163ffffffff61331916565b6000888152600960205260409020600a015490935061403c9061402f90839063ffffffff6132b816565b849063ffffffff61337216565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a9052915193965061411793919092169163ef5fa322916044808301926020929190829003018186803b15801561409757600080fd5b505afa1580156140ab573d6000803e3d6000fd5b505050506040513d60208110156140c157600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b90529151919092169163efeecb04916044808301926020929190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600a810154600790910154919550614153916141469163ffffffff61331916565b859063ffffffff6132b816565b6000888152600960205260409020600a015490945061418a9061417d90839063ffffffff6132b816565b859063ffffffff61337216565b600088815260096020526040902060088101546007820154600a90920154929650614203926141db926305f5e100926111f19290916141cf919063ffffffff61331916565b9063ffffffff61331916565b60008981526009602052604090206006810154600a909101546114e89163ffffffff61331916565b6000888152600960205260408120600c810192909255600d820155600a015461423390829063ffffffff6132b816565b600088815260096020908152604091829020600e019290925560015481516301864ba360e41b81526001600160a01b038a81166004830152602482018a905292519290911692631864ba3092604480840193829003018186803b15801561429957600080fd5b505afa1580156142ad573d6000803e3d6000fd5b505050506040513d60208110156142c357600080fd5b50516000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b50505050505050565b60008181526009602090815260408083208054600180830154600a90930154905484516377afd19160e11b81526001600160a01b039384166004820181905260248201869052955195979496949561437c9593949092169263ef5fa32292604480840193829003018186803b1580156138dc57600080fd5b9050600061438985614d37565b600154604080516377afd19160e11b81526001600160a01b03888116600483015260248201889052915193945060009384938493169163ef5fa322916044808301926020929190829003018186803b1580156143e457600080fd5b505afa1580156143f8573d6000803e3d6000fd5b505050506040513d602081101561440e57600080fd5b50516000898152600960205260409020600a0154141561443a5750600091508190506305f5e1006145c9565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b15801561448e57600080fd5b505afa1580156144a2573d6000803e3d6000fd5b505050506040513d60208110156144b857600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193965091169163efeecb0491604480820192602092909190829003018186803b15801561451057600080fd5b505afa158015614524573d6000803e3d6000fd5b505050506040513d602081101561453a57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193955091169163faddee1491604480820192602092909190829003018186803b15801561459257600080fd5b505afa1580156145a6573d6000803e3d6000fd5b505050506040513d60208110156145bc57600080fd5b505190506145c9886151f4565b6000888152600960209081526040808320600c810193909355600d8301879055600e90920187905560015482516301864ba360e41b81526001600160a01b038b81166004830152602482018b905293519390911692631864ba3092604480840193919291829003018186803b15801561464157600080fd5b505afa158015614655573d6000803e3d6000fd5b505050506040513d602081101561466b57600080fd5b50516000898152600960205260409020600f8101919091556010810184905560118101839055601201819055613c3b886152fe565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b15801561471157600080fd5b505afa158015614725573d6000803e3d6000fd5b505050506040513d602081101561473b57600080fd5b505190506305f5e10081101561475257506305f5e1005b614766816305f5e10063ffffffff6132b816565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b905294519596506147d79592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b15801561483057600080fd5b505afa158015614844573d6000803e3d6000fd5b505050506040513d602081101561485a57600080fd5b505110156148fb5760015460408051633eb77b8560e21b81526001600160a01b0388811660048301526024820188905291516148f493929092169163faddee1491604480820192602092909190829003018186803b1580156148bb57600080fd5b505afa1580156148cf573d6000803e3d6000fd5b505050506040513d60208110156148e557600080fd5b5051829063ffffffff6133b416565b90506148ff565b5060005b600154604080516301864ba360e41b81526001600160a01b038881166004830152602482018890529151600093614964936305f5e100936111f1939190921691631864ba30916044808301926020929190829003018186803b158015613f0757600080fd5b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a905291519394506149c2938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600b8101546008909101549194506149f1916112a49163ffffffff61331916565b6000888152600960205260409020600b0154909350614a1b9061402f90839063ffffffff6132b816565b600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a90529151939650614a76939190921691631864ba30916044808301926020929190829003018186803b15801561409757600080fd5b6000888152600960205260409020600b810154600790910154919550614aa5916141469163ffffffff61331916565b6000888152600960205260409020600b0154909450614acf9061417d90839063ffffffff6132b816565b600088815260096020526040902060088101546007820154600b90920154929650614b3c92614b14926305f5e100926111f19290916141cf919063ffffffff61331916565b60008981526009602052604090206006810154600b909101546114e89163ffffffff61331916565b6000888152600960209081526040808320600c810194909455600d9093019190915560015482516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529351939091169263ef5fa32292604480840193919291829003018186803b158015614bae57600080fd5b505afa158015614bc2573d6000803e3d6000fd5b505050506040513d6020811015614bd857600080fd5b50516000888152600960205260409020600e810191909155600b0154614c0590829063ffffffff6132b816565b6000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b60008183614cc75760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614c8c578181015183820152602001614c74565b50505050905090810190601f168015614cb95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581614cd357fe5b0495945050505050565b60008184841115614d2f5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614c8c578181015183820152602001614c74565b505050900390565b6000818152600960205260408120805460018201546004909201546001600160a01b039091169190839060ff16614fa857600085815260096020908152604091829020600a0154600154835163e291f13560e01b81526001600160a01b038881166004830152602482018890529451929850614fa1949091169263e291f13592604480840193829003018186803b158015614dd157600080fd5b505afa158015614de5573d6000803e3d6000fd5b505050506040513d6020811015614dfb57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b158015614e5157600080fd5b505afa158015614e65573d6000803e3d6000fd5b505050506040513d6020811015614e7b57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b158015614ed157600080fd5b505afa158015614ee5573d6000803e3d6000fd5b505050506040513d6020811015614efb57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b158015614f6e57600080fd5b505afa158015614f82573d6000803e3d6000fd5b505050506040513d6020811015614f9857600080fd5b50516001611389565b90506151e4565b600085815260096020908152604091829020600b0154600154835163e291f13560e01b81526001600160a01b0388811660048301526024820188905294519298506151e1949091169263e291f13592604480840193829003018186803b15801561501157600080fd5b505afa158015615025573d6000803e3d6000fd5b505050506040513d602081101561503b57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b15801561509157600080fd5b505afa1580156150a5573d6000803e3d6000fd5b505050506040513d60208110156150bb57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b15801561511157600080fd5b505afa158015615125573d6000803e3d6000fd5b505050506040513d602081101561513b57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b1580156151ae57600080fd5b505afa1580156151c2573d6000803e3d6000fd5b505050506040513d60208110156151d857600080fd5b5051600161118b565b90505b611922848263ffffffff61331916565b6000818152600960209081526040808320805460019182015491548351630f5fd3cf60e21b81526001600160a01b03928316600482018190526024820185905294519496939593949290911692633d7f4f3c92604480840193829003018186803b15801561526157600080fd5b505afa158015615275573d6000803e3d6000fd5b505050506040513d602081101561528b57600080fd5b50516000858152600960208181526040928390209091015482518881529182015280820183905290519192507f8c75318cfd6a0eae2329289b6827fd382e7324865986be09126ce67fc55bedc2919081900360600190a16000938452600960208190526040909420909301929092555050565b600081815260096020908152604091829020600c810154600d820154600154925485516370a0823160e01b81526001600160a01b039182166004820152955192956153a595929491909116926370a0823192602480840193919291829003018186803b15801561536d57600080fd5b505afa158015615381573d6000803e3d6000fd5b505050506040513d602081101561539757600080fd5b50519063ffffffff6132b816565b10156153e25760405162461bcd60e51b8152600401808060200182810382526027815260200180615b6d6027913960400191505060405180910390fd5b6153eb816112c1565b506000818152600960205260409020600c810154600d90910154111561544b576000818152600960205260409020600c810154600d909101546154339163ffffffff6133b416565b506000818152600960205260408120600c0155615487565b6000818152600960205260409020600d810154600c909101546154739163ffffffff6133b416565b506000818152600960205260408120600d01555b6000818152600960205260409020600d01541561551e576003546000828152600960205260408082208054600d9091015482516340c10f1960e01b81526001600160a01b039283166004820152602481019190915291519316926340c10f199260448084019391929182900301818387803b15801561550557600080fd5b505af1158015615519573d6000803e3d6000fd5b505050505b6000818152600960205260409020600c0154156155b5576001546000828152600960205260408082208054600c909101548251632770a7eb60e21b81526001600160a01b03928316600482015260248101919091529151931692639dc29fac9260448084019391929182900301818387803b15801561559c57600080fd5b505af11580156155b0573d6000803e3d6000fd5b505050505b60018054600083815260096020819052604080832080549581015492810154600e820154600f8301546010840154601185015460128601546013909601548751635f3f325b60e11b81526001600160a01b039c8d166004820152602481019990995260448901959095526064880193909352608487019190915260a486015260c485015260e484019190915261010483015251939092169263be7e64b69261012480820193929182900301818387803b15801561567157600080fd5b505af1158015615685573d6000803e3d6000fd5b5050506000828152600960208181526040928390208054600182015493820154600e830154600f8401546010850154601186015460128701546013880154600d890154600c909901548c516001600160a01b0390991689529988019a909a52868b01959095526060860193909352608085019190915260a084015260c083015260e082015261010081019390935261012083015261014082015290517f39cf7e0047b8651259e011d0b3ed8fc2c3dc2e49ed041f1651f06429698c1c949250908190036101600190a15056fe4d6f72706865725472616465456e67696e653a206c657665726167652065786365656473206d6178696d756d20616c6c6f776564206c657665726167652e4d6f72706865725472616465456e67696e653a204465616374697661746564206d61726b6574206f72646572206e6565647320616c6c2073686172657320746f20626520636c6f7365644d6f72706865725472616465456e67696e653a2043616e2774207061727469616c6c7920636c6f7365206120706f736974696f6e20616e64206f70656e20616e6f74686572206f6e6520696e206f70706f7369746520646972656374696f6e4d6f72706865725472616465456e67696e653a2072657175657374206578636565646564206d6178696d756d207065726d69747465642072657175657374732070657220626c6f636b2e4d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220646f6573206e6f742065786973742e4d6f72706865725472616465456e67696e653a2043616e277420636c6f7365206120706f736974696f6e2c206d61726b6574206e6f742061637469766520616e6420636c6f73696e67207072696365206e6f74206c6f636b65644d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220686173206265656e2064656c657465642e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e4d6f72706865725472616465456e67696e653a206f6e6c792041646d696e6973747261746f72206f7220757365722063616e2063616e63656c20616e206f726465722e4d6f72706865725472616465456e67696e653a206d61726b6574207072696365206c6f776572207468656e206d61726b6574207370726561642e204f726465722063616e6e6f742062652070726f6365737365642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f72706865725472616465456e67696e653a2066756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279204f7261636c6520436f6e74726163742e4d6f72706865725472616465456e67696e653a206d61726b657420756e6b6e6f776e206f722063757272656e746c79206e6f7420656e61626c656420666f722074726164696e672e4d6f72706865725472616465456e67696e653a206c6576657261676520746f6f20736d616c6c2e204c6576657261676520707265636973696f6e206973203165384d6f72706865725472616465456e67696e653a206d61726b657420707269636564206174207a65726f2e20427579206f726465722063616e6e6f742062652070726f6365737365642e4f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e4d6f72706865725472616465456e67696e653a20696e73756666696369656e742066756e64732ea265627a7a72315820cb9a00bd74f3aa4fa52897b6a4e7577ae149655caffe63aac6692578ab03023a64736f6c634300051000324f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e04f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e0000000000000000000000001f426c51f0ef7655a6f4c3eb58017d2f1c381bff00000000000000000000000051c5ce7c4926d5ca74f4824e11a062f1ef491762000000000000000000000000baf121d02e6948d3a089f99ddc522eb2a4a1b1fe0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d90c8a36fff52f1c8c05b54d4ce79610431ec0
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063715018a611610104578063ac8f6f7f116100a2578063daf9502711610071578063daf9502714610575578063dc39d06d1461059b578063f2fde38b146105c7578063f40b7b32146105ed576101cf565b8063ac8f6f7f146104dc578063ac9eee2814610522578063b2bdfa7b14610541578063d61aed7a14610549576101cf565b806380104668116100de57806380104668146104895780638da5cb5b146104af5780638f32d59b146104b7578063a386fb56146104bf576101cf565b8063715018a61461042a5780637993a991146104325780637dffd04014610458576101cf565b80634702513c116101715780635778472a1161014b5780635778472a146103755780636950baa8146103d45780636b4f7065146103dc5780637023b78314610405576101cf565b80634702513c1461030d578063480ee2071461032a5780635662ecc71461036d576101cf565b806316f77a5b116101ad57806316f77a5b1461027357806316f8de89146102a857806323aab432146102c25780633754c565146102ca576101cf565b80630fa8f516146101d457806316194bac14610233578063169674071461024f575b600080fd5b610200600480360360408110156101ea57600080fd5b506001600160a01b0381351690602001356105f5565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b61023b610942565b604080519115158252519081900360200190f35b610257610952565b604080516001600160a01b039092168252519081900360200190f35b610200600480360360a081101561028957600080fd5b50803590602081013590604081013590606081013590608001356109c8565b6102b0611176565b60408051918252519081900360200190f35b61025761117c565b6102b0600480360360e08110156102e057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c00135151561118b565b6102b06004803603602081101561032357600080fd5b50356112c1565b6102b0600480360360e081101561034057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c001351515611389565b6102b061140c565b6103926004803603602081101561038b57600080fd5b5035611412565b604080516001600160a01b0390981688526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b610257611459565b6102b0600480360360608110156103f257600080fd5b5080359060208101359060400135611468565b6104286004803603604081101561041b57600080fd5b50803590602001356115a5565b005b610428611765565b6104286004803603602081101561044857600080fd5b50356001600160a01b03166117f6565b6102b06004803603608081101561046e57600080fd5b50803590602081013590604081013515159060600135611891565b6104286004803603602081101561049f57600080fd5b50356001600160a01b031661192b565b6102576119c6565b61023b6119d5565b6102b0600480360360208110156104d557600080fd5b50356119e6565b6102b0600480360360c08110156104f257600080fd5b506001600160a01b0381351690602081013590604081013590606081013590608081013515159060a00135611a75565b6104286004803603602081101561053857600080fd5b50351515612226565b61025761228b565b6104286004803603604081101561055f57600080fd5b50803590602001356001600160a01b031661229a565b6104286004803603602081101561058b57600080fd5b50356001600160a01b0316612517565b61023b600480360360408110156105b157600080fd5b506001600160a01b0381351690602001356125b2565b610428600480360360208110156105dd57600080fd5b50356001600160a01b0316612697565b6102b06126ea565b600154604080516377afd19160e11b81526001600160a01b03858116600483015260248201859052915160009384938493849384938493169163ef5fa322916044808301926020929190829003018186803b15801561065357600080fd5b505afa158015610667573d6000803e3d6000fd5b505050506040513d602081101561067d57600080fd5b5051600154604080516301864ba360e41b81526001600160a01b038c81166004830152602482018c905291519190921691631864ba30916044808301926020929190829003018186803b1580156106d357600080fd5b505afa1580156106e7573d6000803e3d6000fd5b505050506040513d60208110156106fd57600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038d81166004830152602482018d90529151919092169163e291f135916044808301926020929190829003018186803b15801561075357600080fd5b505afa158015610767573d6000803e3d6000fd5b505050506040513d602081101561077d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038e81166004830152602482018e90529151919092169163efeecb04916044808301926020929190829003018186803b1580156107d357600080fd5b505afa1580156107e7573d6000803e3d6000fd5b505050506040513d60208110156107fd57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038f81166004830152602482018f90529151919092169163faddee14916044808301926020929190829003018186803b15801561085357600080fd5b505afa158015610867573d6000803e3d6000fd5b505050506040513d602081101561087d57600080fd5b8101908080519060200190929190505050600160009054906101000a90046001600160a01b03166001600160a01b031663652f17638e8e6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b15801561090157600080fd5b505afa158015610915573d6000803e3d6000fd5b505050506040513d602081101561092b57600080fd5b5051949d939c50919a509850965090945092505050565b600754600160a01b900460ff1681565b60015460408051631696740760e01b815290516000926001600160a01b0316916316967407916004808301926020929190829003018186803b15801561099757600080fd5b505afa1580156109ab573d6000803e3d6000fd5b505050506040513d60208110156109c157600080fd5b5051905090565b600080600080600080600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1f57600080fd5b505afa158015610a33573d6000803e3d6000fd5b505050506040513d6020811015610a4957600080fd5b50516001600160a01b03163314610a915760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b60008b8152600960205260409020546001600160a01b0316610ae45760405162461bcd60e51b815260040180806020018281038252603e815260200180615919603e913960400191505060405180910390fd5b60008a11610b235760405162461bcd60e51b8152600401808060200182810382526049815260200180615b046049913960600191505060405180910390fd5b888a1015610b625760405162461bcd60e51b81526004018080602001828103825260558152602001806159c26055913960600191505060405180910390fd5b60008b815260096020818152604092839020600681018e9055600781018d90559182018a9055600582018b9055600180549201548351634a4cce9760e01b8152600481019190915292516001600160a01b0390921692634a4cce979260248083019392829003018186803b158015610bd957600080fd5b505afa158015610bed573d6000803e3d6000fd5b505050506040513d6020811015610c0357600080fd5b5051610c4057610c128b6126f0565b60008b815260096020526040902060010154610c2d906119e6565b60008c8152600960205260409020600601555b6001805460008d81526009602090815260409182902080549401548251630f5fd3cf60e21b81526001600160a01b039586166004820152602481019190915291519390921692633d7f4f3c92604480840193919291829003018186803b158015610ca957600080fd5b505afa158015610cbd573d6000803e3d6000fd5b505050506040513d6020811015610cd357600080fd5b5051881115610ce557610ce58b61272e565b610cee8b612c41565b60008b81526009602052604090206004015460ff1615610d1657610d118b612cea565b610d1f565b610d1f8b612fe0565b60008b815260096020818152604080842080546001820180546001600160a01b03198316845590879055600283018790556003830187905560048301805460ff1916905560058301879055600683018790556007830187905560088301879055948201869055600a8201869055600b8201869055600c8201869055600d8201869055600e8201869055600f82018690556010820186905560118201869055601282018690556013820186905560149091019490945580518f81529182018e90528181018d9052606082018c9052608082018b905260a082018a905260c0820189905260e08201889052610100820187905261012082018690526101408201859052516001600160a01b03909316927f696a3d28d7b4bcfc9cbfef719a03218d7a502cda20d01f9ef8086249e8165492918190036101600190a1600154604080516377afd19160e11b81526001600160a01b038581166004830152602482018590529151919092169163ef5fa322916044808301926020929190829003018186803b158015610eac57600080fd5b505afa158015610ec0573d6000803e3d6000fd5b505050506040513d6020811015610ed657600080fd5b5051600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291519190921691631864ba30916044808301926020929190829003018186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d6020811015610f5657600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038781166004830152602482018790529151919092169163e291f135916044808301926020929190829003018186803b158015610fac57600080fd5b505afa158015610fc0573d6000803e3d6000fd5b505050506040513d6020811015610fd657600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038881166004830152602482018890529151919092169163efeecb04916044808301926020929190829003018186803b15801561102c57600080fd5b505afa158015611040573d6000803e3d6000fd5b505050506040513d602081101561105657600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038981166004830152602482018990529151919092169163faddee14916044808301926020929190829003018186803b1580156110ac57600080fd5b505afa1580156110c0573d6000803e3d6000fd5b505050506040513d60208110156110d657600080fd5b50516001546040805163652f176360e01b81526001600160a01b038a81166004830152602482018a90529151919092169163652f1763916044808301926020929190829003018186803b15801561112c57600080fd5b505afa158015611140573d6000803e3d6000fd5b505050506040513d602081101561115657600080fd5b5051949c50929a5090985096509450925050509550955095509550955095565b60045481565b6008546001600160a01b031681565b600087876305f5e1008110156111a257506305f5e1005b836111ad5750859050835b866111bb838360008c611891565b116111c957600092506112b4565b6111fd6305f5e1006111f16111e4828563ffffffff6132b816565b859063ffffffff61331916565b9063ffffffff61337216565b925061122761121a6305f5e1006111f18a8563ffffffff61331916565b849063ffffffff6133b416565b9250600184151514156112895761124f61121a6305f5e1006111f1898563ffffffff61331916565b9250600061125e83838b611468565b905083811161127e57611277848263ffffffff6133b416565b9350611283565b600093505b506112b4565b6112b16112a46305f5e1006111f1898963ffffffff61331916565b849063ffffffff6132b816565b92505b5050979650505050505050565b600081815260096020526040812060138101829055600e01541561132057600082815260096020819052604090912060108101546012820154919092015461130d929190600190611891565b6000838152600960205260409020601301555b6000828152600960205260409020600f01541561137357600082815260096020819052604082206010810154601282015491909201546113609390611891565b6000838152600960205260409020601301555b5060009081526009602052604090206013015490565b600087876305f5e1008110156113a057506305f5e1005b836113ab5750859050835b6113b8828260018b611891565b87116113c757600092506112b4565b6113e26305f5e1006111f16111e4848363ffffffff6133b416565b9250611227836114006305f5e1006111f18b8663ffffffff61331916565b9063ffffffff6133b416565b60055481565b60009081526009602052604090208054600182015460028301546003840154600685015460078601546008909601546001600160a01b039095169693959294919390929190565b6007546001600160a01b031681565b600654600090611480836103e863ffffffff61337216565b101561149e5760065461149b906103e863ffffffff61331916565b91505b6114b56111e4846305f5e10063ffffffff6133b416565b90506115016114f460016114e8620151806111f16114db886103e863ffffffff61337216565b429063ffffffff6133b416565b9063ffffffff6132b816565b829063ffffffff61331916565b905061159d6305f5e1006111f16305f5e1006111f1600260009054906101000a90046001600160a01b03166001600160a01b0316637c3a00fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561156457600080fd5b505afa158015611578573d6000803e3d6000fd5b505050506040513d602081101561158e57600080fd5b5051869063ffffffff61331916565b949350505050565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f357600080fd5b505afa158015611607573d6000803e3d6000fd5b505050506040513d602081101561161d57600080fd5b50516001600160a01b031633146116655760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6001546008546001600160a01b039182169163be7e64b6911684611691426103e863ffffffff61331916565b604080516001600160e01b031960e087901b1681526001600160a01b039094166004850152602484019290925260448301526000606483018190526084830181905260a4830186905260c4830181905260e48301819052610104830181905290516101248084019382900301818387803b15801561170e57600080fd5b505af1158015611722573d6000803e3d6000fd5b5050604080518581526020810185905281517f3cf30f15febef0d3f8e86318070db2c80d03fd14e8406d326aab41cb043f18399450908190039091019150a15050565b61176d6119d5565b6117ac576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6117fe6119d5565b61183d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4016bbc93bb2adf11f6d1b2509a1ab5f593cbe26e54875655329f9c80117f0849181900360200190a150565b6000600183151514156118ea576118c6846111f16118b9826305f5e10063ffffffff6133b416565b889063ffffffff61331916565b90506118e36118d6868685611468565b829063ffffffff6132b816565b905061159d565b611905846111f16118b9826305f5e10063ffffffff6132b816565b9050611922611915868685611468565b829063ffffffff6133b416565b95945050505050565b6119336119d5565b611972576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f978c711532bae8c58f353b0f3c7f3a0dfe600d9ae9a81818f2ad2919b88e19909181900360200190a150565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600154600854604080516307d47a8b60e11b81526001600160a01b03928316600482015260248101859052905160009384931691630fa8f5169160448083019260c0929190829003018186803b158015611a3f57600080fd5b505afa158015611a53573d6000803e3d6000fd5b505050506040513d60c0811015611a6957600080fd5b50604001519392505050565b6001546040805163e3bbb56560e01b815290516000926001600160a01b03169163e3bbb565916004808301926020929190829003018186803b158015611aba57600080fd5b505afa158015611ace573d6000803e3d6000fd5b505050506040513d6020811015611ae457600080fd5b50516001600160a01b03163314611b2c5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6305f5e100821015611b6f5760405162461bcd60e51b8152600401808060200182810382526041815260200180615ac36041913960600191505060405180910390fd5b600160009054906101000a90046001600160a01b03166001600160a01b0316637c995e916040518163ffffffff1660e01b815260040160206040518083038186803b158015611bbd57600080fd5b505afa158015611bd1573d6000803e3d6000fd5b505050506040513d6020811015611be757600080fd5b5051821115611c275760405162461bcd60e51b815260040180806020018281038252603e815260200180615752603e913960400191505060405180910390fd5b611c3487878787876133f6565b600160009054906101000a90046001600160a01b03166001600160a01b031663755ca87a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8257600080fd5b505afa158015611c96573d6000803e3d6000fd5b505050506040513d6020811015611cac57600080fd5b505160015460408051631722e4cd60e21b81526001600160a01b038b8116600483015291519190921691635c8b9334916024808301926020929190829003018186803b158015611cfb57600080fd5b505afa158015611d0f573d6000803e3d6000fd5b505050506040513d6020811015611d2557600080fd5b5051111580611dad5750600154604080516330826beb60e21b81526001600160a01b038a8116600483015291514393929092169163c209afac91602480820192602092909190829003018186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d6020811015611da957600080fd5b5051105b611de85760405162461bcd60e51b815260040180806020018281038252604a815260200180615839604a913960600191505060405180910390fd5b8315611f73578215611eb657600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a905291519190921691631864ba30916044808301926020929190829003018186803b158015611e4857600080fd5b505afa158015611e5c573d6000803e3d6000fd5b505050506040513d6020811015611e7257600080fd5b50518514611eb15760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b611f73565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529151919092169163ef5fa322916044808301926020929190829003018186803b158015611f0a57600080fd5b505afa158015611f1e573d6000803e3d6000fd5b505050506040513d6020811015611f3457600080fd5b50518514611f735760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b600154604080516303d4880760e11b81526001600160a01b038a81166004830152915191909216916307a9100e91602480830192600092919082900301818387803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b505060015460408051635e61f1a160e11b81526001600160a01b038c81166004830152915191909216935063bcc3e3429250602480830192600092919082900301818387803b15801561202757600080fd5b505af115801561203b573d6000803e3d6000fd5b505050506004600081548092919060010191905055508643878787878760045460405160200180896001600160a01b03166001600160a01b031660601b8152601401888152602001878152602001868152602001858152602001841515151560f81b81526001018381526020018281526020019850505050505050505060405160208183030381529060405280519060200120905080600581905550866009600083815260200190815260200160002060000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550856009600083815260200190815260200160002060010181905550846009600083815260200190815260200160002060020181905550836009600083815260200190815260200160002060030181905550826009600083815260200190815260200160002060040160006101000a81548160ff02191690831515021790555081600960008381526020019081526020016000206008018190555085876001600160a01b03167fd5dec9e768ba83c154ee9ecf7a0c145c8e7ee75e1cc4af2d271a1f9c93bb3946838888888860405180868152602001858152602001848152602001831515151581526020018281526020019550505050505060405180910390a361221c8185613703565b9695505050505050565b61222e6119d5565b61226d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b60078054911515600160a01b0260ff60a01b19909216919091179055565b6000546001600160a01b031681565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156122e857600080fd5b505afa1580156122fc573d6000803e3d6000fd5b505050506040513d602081101561231257600080fd5b50516001600160a01b0316331461235a5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b038281169116148061239a5750612385610952565b6001600160a01b0316816001600160a01b0316145b6123d55760405162461bcd60e51b815260040180806020018281038252604381526020018061597f6043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b03166124285760405162461bcd60e51b815260040180806020018281038252603c815260200180615883603c913960400191505060405180910390fd5b61243182612c41565b600082815260096020819052604080832080546001600160a01b031916815560018101849055600281018490556003810184905560048101805460ff1916905560058101849055600681018490556007810184905560088101849055918201839055600a8201839055600b8201839055600c8201839055600d8201839055600e8201839055600f8201839055601082018390556011820183905560128201839055601382018390556014909101829055516001600160a01b0383169184917fa6eb7cdc219e1518ced964e9a34e61d68a94e4f1569db3e84256ba981ba527539190a35050565b61251f6119d5565b61255e576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600380546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f42c6bffb0e058cc1dfabd910037516fb01b87949d9a476876ff43179d62f4dc89181900360200190a150565b60006125bc6119d5565b6125fb576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6126126119c6565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561266257600080fd5b505af1158015612676573d6000803e3d6000fd5b505050506040513d602081101561268c57600080fd5b505190505b92915050565b61269f6119d5565b6126de576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b6126e7816137bc565b50565b60065481565b600081815260096020526040902080546001820154600283015460038401546004909401546126e7946001600160a01b03909416939060ff166133f6565b600081815260096020908152604091829020805460018083015460059093015490548551630f5fd3cf60e21b81526001600160a01b0393841660048201819052602482018690529651949592949190931692633d7f4f3c926044808301939192829003018186803b1580156127a257600080fd5b505afa1580156127b6573d6000803e3d6000fd5b505050506040513d60208110156127cc57600080fd5b5051811115612c3b57600154604080516377afd19160e11b81526001600160a01b038681166004830152602482018690529151600093929092169163ef5fa32291604480820192602092909190829003018186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d602081101561285757600080fd5b50511115612a0a5760015460008581526009602081815260408084209092015482516301864ba360e41b81526001600160a01b038981166004830152602482018990529351939095169463be7e64b6948994899491928892631864ba3092604480840193829003018186803b1580156128cf57600080fd5b505afa1580156128e3573d6000803e3d6000fd5b505050506040513d60208110156128f957600080fd5b5051604080516001600160e01b031960e089901b1681526001600160a01b0390961660048701526024860194909452604485019290925260648401526084830152600060a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b15801561297a57600080fd5b505af115801561298e573d6000803e3d6000fd5b5050506000858152600960208181526040928390209182015460068301546007909301548451600181529283019190915281840192909252606081019190915290518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291516000939290921691631864ba3091604480820192602092909190829003018186803b158015612a6257600080fd5b505afa158015612a76573d6000803e3d6000fd5b505050506040513d6020811015612a8c57600080fd5b50511115612c3b576001546000858152600960208181526040928390209091015482516377afd19160e11b81526001600160a01b038881166004830152602482018890529351939094169363be7e64b6938893889392879263ef5fa32292604480840193919291829003018186803b158015612b0757600080fd5b505afa158015612b1b573d6000803e3d6000fd5b505050506040513d6020811015612b3157600080fd5b5051604080516001600160e01b031960e088901b1681526001600160a01b03909516600486015260248501939093526044840191909152606483015260006084830181905260a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b158015612bb457600080fd5b505af1158015612bc8573d6000803e3d6000fd5b5050506000858152600960208181526040808420928301546006840154600790940154825195865292850152838101929092526060830152518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b50505050565b600081815260096020526040902060140154156126e75760008181526009602052604080822060148101805490849055600154600754925484516317d5759960e31b81526001600160a01b0394851660048201529084166024820152604481018390529351919492169263beabacc892606480830193919282900301818387803b158015612cce57600080fd5b505af1158015612ce2573d6000803e3d6000fd5b505050505050565b60008181526009602052604090206002015415612e735760018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612d6a57600080fd5b505afa158015612d7e573d6000803e3d6000fd5b505050506040513d6020811015612d9457600080fd5b505160008281526009602052604090206002015411612dcb5760008181526009602052604090206002810154600b90910155612e73565b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612e3457600080fd5b505afa158015612e48573d6000803e3d6000fd5b505050506040513d6020811015612e5e57600080fd5b50516000828152600960205260409020600b01555b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612edc57600080fd5b505afa158015612ef0573d6000803e3d6000fd5b505050506040513d6020811015612f0657600080fd5b50516000828152600960205260409020600b0154148015612f37575060008181526009602052604090206003015415155b15612fa057600081815260096020526040812060068101546008820154600790920154612f8d93612f6f939142918491908490611389565b6000838152600960205260409020600301549063ffffffff61337216565b6000828152600960205260409020600a01555b6000818152600960205260409020600b015415612fc057612fc08161385c565b6000818152600960205260409020600a0154156126e7576126e781613c45565b600081815260096020526040902060020154156131695760018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561306057600080fd5b505afa158015613074573d6000803e3d6000fd5b505050506040513d602081101561308a57600080fd5b5051600082815260096020526040902060020154116130c15760008181526009602052604090206002810154600a90910155613169565b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561312a57600080fd5b505afa15801561313e573d6000803e3d6000fd5b505050506040513d602081101561315457600080fd5b50516000828152600960205260409020600a01555b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b1580156131d257600080fd5b505afa1580156131e6573d6000803e3d6000fd5b505050506040513d60208110156131fc57600080fd5b50516000828152600960205260409020600a015414801561322d575060008181526009602052604090206003015415155b156132785760008181526009602052604081206006810154600882015460079092015461326593612f6f93914291849190849061118b565b6000828152600960205260409020600b01555b6000818152600960205260409020600a0154156132985761329881614304565b6000818152600960205260409020600b0154156126e7576126e7816146a0565b600082820183811015613312576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008261332857506000612691565b8282028284828161333557fe5b04146133125760405162461bcd60e51b8152600401808060200182810382526021815260200180615a176021913960400191505060405180910390fd5b600061331283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614c3b565b600061331283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614cdd565b81156134b95760015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561344857600080fd5b505afa15801561345c573d6000803e3d6000fd5b505050506040513d602081101561347257600080fd5b505115156001146134b45760405162461bcd60e51b8152600401808060200182810382526048815260200180615a7b6048913960600191505060405180910390fd5b6136fc565b60015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561350557600080fd5b505afa158015613519573d6000803e3d6000fd5b505050506040513d602081101561352f57600080fd5b50516136fc576000613540856119e6565b1161357c5760405162461bcd60e51b815260040180806020018281038252605a8152602001806158bf605a913960600191505060405180910390fd5b801561363f57600154604080516301864ba360e41b81526001600160a01b0388811660048301526024820188905291519190921691631864ba30916044808301926020929190829003018186803b1580156135d657600080fd5b505afa1580156135ea573d6000803e3d6000fd5b505050506040513d602081101561360057600080fd5b505183146134b45760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151919092169163ef5fa322916044808301926020929190829003018186803b15801561369357600080fd5b505afa1580156136a7573d6000803e3d6000fd5b505050506040513d60208110156136bd57600080fd5b505183146136fc5760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b5050505050565b600754600160a01b900460ff16801561371c5750600081115b156137b8576001546000838152600960205260408082205460075482516317d5759960e31b81526001600160a01b039283166004820152908216602482015260448101869052915193169263beabacc89260648084019391929182900301818387803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b5050506000838152600960205260409020601401829055505b5050565b6001600160a01b0381166138015760405162461bcd60e51b81526004018080602001828103825260288152602001806159576028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008181526009602090815260408083208054600180830154600b90930154905484516301864ba360e41b81526001600160a01b0393841660048201819052602482018690529551959794969495869586958695613914959094911692631864ba3092604480840193919291829003018186803b1580156138dc57600080fd5b505afa1580156138f0573d6000803e3d6000fd5b505050506040513d602081101561390657600080fd5b50519063ffffffff6133b416565b9050600061392188614d37565b600154604080516301864ba360e41b81526001600160a01b038b81166004830152602482018b90529151939450911691631864ba3091604480820192602092909190829003018186803b15801561397757600080fd5b505afa15801561398b573d6000803e3d6000fd5b505050506040513d60208110156139a157600080fd5b50516000898152600960205260409020600b015414156139cf5760009450600093506305f5e1009250613b5e565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193985091169163efeecb0491604480820192602092909190829003018186803b158015613aa557600080fd5b505afa158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193975091169163faddee1491604480820192602092909190829003018186803b158015613b2757600080fd5b505afa158015613b3b573d6000803e3d6000fd5b505050506040513d6020811015613b5157600080fd5b50519250613b5e886151f4565b6000888152600960209081526040808320600c810193909355600d8301849055600180548454919094015482516377afd19160e11b81526001600160a01b0392831660048201526024810191909152915193169263ef5fa32292604480840193919291829003018186803b158015613bd557600080fd5b505afa158015613be9573d6000803e3d6000fd5b505050506040513d6020811015613bff57600080fd5b50516000898152600960205260409020600e810191909155600f81018390556010810186905560118101859055601201839055613c3b886152fe565b5050505050505050565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b158015613cb657600080fd5b505afa158015613cca573d6000803e3d6000fd5b505050506040513d6020811015613ce057600080fd5b505190506305f5e100811015613cf757506305f5e1005b613d0b816305f5e10063ffffffff6133b416565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b90529451959650613db59592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b505afa158015613d90573d6000803e3d6000fd5b505050506040513d6020811015613da657600080fd5b5051849063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b158015613e0e57600080fd5b505afa158015613e22573d6000803e3d6000fd5b505050506040513d6020811015613e3857600080fd5b50511115613e9e5760015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151613e97938593169163faddee14916044808301926020929190829003018186803b1580156138dc57600080fd5b9050613ea2565b5060005b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151600093613f40936305f5e100936111f193919092169163ef5fa322916044808301926020929190829003018186803b158015613f0757600080fd5b505afa158015613f1b573d6000803e3d6000fd5b505050506040513d6020811015613f3157600080fd5b5051859063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a90529151939450613fd6938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b505afa158015613fb2573d6000803e3d6000fd5b505050506040513d6020811015613fc857600080fd5b50519063ffffffff61331916565b6000888152600960205260409020600a810154600890910154919450614005916112a49163ffffffff61331916565b6000888152600960205260409020600a015490935061403c9061402f90839063ffffffff6132b816565b849063ffffffff61337216565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a9052915193965061411793919092169163ef5fa322916044808301926020929190829003018186803b15801561409757600080fd5b505afa1580156140ab573d6000803e3d6000fd5b505050506040513d60208110156140c157600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b90529151919092169163efeecb04916044808301926020929190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600a810154600790910154919550614153916141469163ffffffff61331916565b859063ffffffff6132b816565b6000888152600960205260409020600a015490945061418a9061417d90839063ffffffff6132b816565b859063ffffffff61337216565b600088815260096020526040902060088101546007820154600a90920154929650614203926141db926305f5e100926111f19290916141cf919063ffffffff61331916565b9063ffffffff61331916565b60008981526009602052604090206006810154600a909101546114e89163ffffffff61331916565b6000888152600960205260408120600c810192909255600d820155600a015461423390829063ffffffff6132b816565b600088815260096020908152604091829020600e019290925560015481516301864ba360e41b81526001600160a01b038a81166004830152602482018a905292519290911692631864ba3092604480840193829003018186803b15801561429957600080fd5b505afa1580156142ad573d6000803e3d6000fd5b505050506040513d60208110156142c357600080fd5b50516000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b50505050505050565b60008181526009602090815260408083208054600180830154600a90930154905484516377afd19160e11b81526001600160a01b039384166004820181905260248201869052955195979496949561437c9593949092169263ef5fa32292604480840193829003018186803b1580156138dc57600080fd5b9050600061438985614d37565b600154604080516377afd19160e11b81526001600160a01b03888116600483015260248201889052915193945060009384938493169163ef5fa322916044808301926020929190829003018186803b1580156143e457600080fd5b505afa1580156143f8573d6000803e3d6000fd5b505050506040513d602081101561440e57600080fd5b50516000898152600960205260409020600a0154141561443a5750600091508190506305f5e1006145c9565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b15801561448e57600080fd5b505afa1580156144a2573d6000803e3d6000fd5b505050506040513d60208110156144b857600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193965091169163efeecb0491604480820192602092909190829003018186803b15801561451057600080fd5b505afa158015614524573d6000803e3d6000fd5b505050506040513d602081101561453a57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193955091169163faddee1491604480820192602092909190829003018186803b15801561459257600080fd5b505afa1580156145a6573d6000803e3d6000fd5b505050506040513d60208110156145bc57600080fd5b505190506145c9886151f4565b6000888152600960209081526040808320600c810193909355600d8301879055600e90920187905560015482516301864ba360e41b81526001600160a01b038b81166004830152602482018b905293519390911692631864ba3092604480840193919291829003018186803b15801561464157600080fd5b505afa158015614655573d6000803e3d6000fd5b505050506040513d602081101561466b57600080fd5b50516000898152600960205260409020600f8101919091556010810184905560118101839055601201819055613c3b886152fe565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b15801561471157600080fd5b505afa158015614725573d6000803e3d6000fd5b505050506040513d602081101561473b57600080fd5b505190506305f5e10081101561475257506305f5e1005b614766816305f5e10063ffffffff6132b816565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b905294519596506147d79592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b15801561483057600080fd5b505afa158015614844573d6000803e3d6000fd5b505050506040513d602081101561485a57600080fd5b505110156148fb5760015460408051633eb77b8560e21b81526001600160a01b0388811660048301526024820188905291516148f493929092169163faddee1491604480820192602092909190829003018186803b1580156148bb57600080fd5b505afa1580156148cf573d6000803e3d6000fd5b505050506040513d60208110156148e557600080fd5b5051829063ffffffff6133b416565b90506148ff565b5060005b600154604080516301864ba360e41b81526001600160a01b038881166004830152602482018890529151600093614964936305f5e100936111f1939190921691631864ba30916044808301926020929190829003018186803b158015613f0757600080fd5b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a905291519394506149c2938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600b8101546008909101549194506149f1916112a49163ffffffff61331916565b6000888152600960205260409020600b0154909350614a1b9061402f90839063ffffffff6132b816565b600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a90529151939650614a76939190921691631864ba30916044808301926020929190829003018186803b15801561409757600080fd5b6000888152600960205260409020600b810154600790910154919550614aa5916141469163ffffffff61331916565b6000888152600960205260409020600b0154909450614acf9061417d90839063ffffffff6132b816565b600088815260096020526040902060088101546007820154600b90920154929650614b3c92614b14926305f5e100926111f19290916141cf919063ffffffff61331916565b60008981526009602052604090206006810154600b909101546114e89163ffffffff61331916565b6000888152600960209081526040808320600c810194909455600d9093019190915560015482516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529351939091169263ef5fa32292604480840193919291829003018186803b158015614bae57600080fd5b505afa158015614bc2573d6000803e3d6000fd5b505050506040513d6020811015614bd857600080fd5b50516000888152600960205260409020600e810191909155600b0154614c0590829063ffffffff6132b816565b6000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b60008183614cc75760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614c8c578181015183820152602001614c74565b50505050905090810190601f168015614cb95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581614cd357fe5b0495945050505050565b60008184841115614d2f5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614c8c578181015183820152602001614c74565b505050900390565b6000818152600960205260408120805460018201546004909201546001600160a01b039091169190839060ff16614fa857600085815260096020908152604091829020600a0154600154835163e291f13560e01b81526001600160a01b038881166004830152602482018890529451929850614fa1949091169263e291f13592604480840193829003018186803b158015614dd157600080fd5b505afa158015614de5573d6000803e3d6000fd5b505050506040513d6020811015614dfb57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b158015614e5157600080fd5b505afa158015614e65573d6000803e3d6000fd5b505050506040513d6020811015614e7b57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b158015614ed157600080fd5b505afa158015614ee5573d6000803e3d6000fd5b505050506040513d6020811015614efb57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b158015614f6e57600080fd5b505afa158015614f82573d6000803e3d6000fd5b505050506040513d6020811015614f9857600080fd5b50516001611389565b90506151e4565b600085815260096020908152604091829020600b0154600154835163e291f13560e01b81526001600160a01b0388811660048301526024820188905294519298506151e1949091169263e291f13592604480840193829003018186803b15801561501157600080fd5b505afa158015615025573d6000803e3d6000fd5b505050506040513d602081101561503b57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b15801561509157600080fd5b505afa1580156150a5573d6000803e3d6000fd5b505050506040513d60208110156150bb57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b15801561511157600080fd5b505afa158015615125573d6000803e3d6000fd5b505050506040513d602081101561513b57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b1580156151ae57600080fd5b505afa1580156151c2573d6000803e3d6000fd5b505050506040513d60208110156151d857600080fd5b5051600161118b565b90505b611922848263ffffffff61331916565b6000818152600960209081526040808320805460019182015491548351630f5fd3cf60e21b81526001600160a01b03928316600482018190526024820185905294519496939593949290911692633d7f4f3c92604480840193829003018186803b15801561526157600080fd5b505afa158015615275573d6000803e3d6000fd5b505050506040513d602081101561528b57600080fd5b50516000858152600960208181526040928390209091015482518881529182015280820183905290519192507f8c75318cfd6a0eae2329289b6827fd382e7324865986be09126ce67fc55bedc2919081900360600190a16000938452600960208190526040909420909301929092555050565b600081815260096020908152604091829020600c810154600d820154600154925485516370a0823160e01b81526001600160a01b039182166004820152955192956153a595929491909116926370a0823192602480840193919291829003018186803b15801561536d57600080fd5b505afa158015615381573d6000803e3d6000fd5b505050506040513d602081101561539757600080fd5b50519063ffffffff6132b816565b10156153e25760405162461bcd60e51b8152600401808060200182810382526027815260200180615b6d6027913960400191505060405180910390fd5b6153eb816112c1565b506000818152600960205260409020600c810154600d90910154111561544b576000818152600960205260409020600c810154600d909101546154339163ffffffff6133b416565b506000818152600960205260408120600c0155615487565b6000818152600960205260409020600d810154600c909101546154739163ffffffff6133b416565b506000818152600960205260408120600d01555b6000818152600960205260409020600d01541561551e576003546000828152600960205260408082208054600d9091015482516340c10f1960e01b81526001600160a01b039283166004820152602481019190915291519316926340c10f199260448084019391929182900301818387803b15801561550557600080fd5b505af1158015615519573d6000803e3d6000fd5b505050505b6000818152600960205260409020600c0154156155b5576001546000828152600960205260408082208054600c909101548251632770a7eb60e21b81526001600160a01b03928316600482015260248101919091529151931692639dc29fac9260448084019391929182900301818387803b15801561559c57600080fd5b505af11580156155b0573d6000803e3d6000fd5b505050505b60018054600083815260096020819052604080832080549581015492810154600e820154600f8301546010840154601185015460128601546013909601548751635f3f325b60e11b81526001600160a01b039c8d166004820152602481019990995260448901959095526064880193909352608487019190915260a486015260c485015260e484019190915261010483015251939092169263be7e64b69261012480820193929182900301818387803b15801561567157600080fd5b505af1158015615685573d6000803e3d6000fd5b5050506000828152600960208181526040928390208054600182015493820154600e830154600f8401546010850154601186015460128701546013880154600d890154600c909901548c516001600160a01b0390991689529988019a909a52868b01959095526060860193909352608085019190915260a084015260c083015260e082015261010081019390935261012083015261014082015290517f39cf7e0047b8651259e011d0b3ed8fc2c3dc2e49ed041f1651f06429698c1c949250908190036101600190a15056fe4d6f72706865725472616465456e67696e653a206c657665726167652065786365656473206d6178696d756d20616c6c6f776564206c657665726167652e4d6f72706865725472616465456e67696e653a204465616374697661746564206d61726b6574206f72646572206e6565647320616c6c2073686172657320746f20626520636c6f7365644d6f72706865725472616465456e67696e653a2043616e2774207061727469616c6c7920636c6f7365206120706f736974696f6e20616e64206f70656e20616e6f74686572206f6e6520696e206f70706f7369746520646972656374696f6e4d6f72706865725472616465456e67696e653a2072657175657374206578636565646564206d6178696d756d207065726d69747465642072657175657374732070657220626c6f636b2e4d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220646f6573206e6f742065786973742e4d6f72706865725472616465456e67696e653a2043616e277420636c6f7365206120706f736974696f6e2c206d61726b6574206e6f742061637469766520616e6420636c6f73696e67207072696365206e6f74206c6f636b65644d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220686173206265656e2064656c657465642e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e4d6f72706865725472616465456e67696e653a206f6e6c792041646d696e6973747261746f72206f7220757365722063616e2063616e63656c20616e206f726465722e4d6f72706865725472616465456e67696e653a206d61726b6574207072696365206c6f776572207468656e206d61726b6574207370726561642e204f726465722063616e6e6f742062652070726f6365737365642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f72706865725472616465456e67696e653a2066756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279204f7261636c6520436f6e74726163742e4d6f72706865725472616465456e67696e653a206d61726b657420756e6b6e6f776e206f722063757272656e746c79206e6f7420656e61626c656420666f722074726164696e672e4d6f72706865725472616465456e67696e653a206c6576657261676520746f6f20736d616c6c2e204c6576657261676520707265636973696f6e206973203165384d6f72706865725472616465456e67696e653a206d61726b657420707269636564206174207a65726f2e20427579206f726465722063616e6e6f742062652070726f6365737365642e4f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e4d6f72706865725472616465456e67696e653a20696e73756666696369656e742066756e64732ea265627a7a72315820cb9a00bd74f3aa4fa52897b6a4e7577ae149655caffe63aac6692578ab03023a64736f6c63430005100032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001f426c51f0ef7655a6f4c3eb58017d2f1c381bff00000000000000000000000051c5ce7c4926d5ca74f4824e11a062f1ef491762000000000000000000000000baf121d02e6948d3a089f99ddc522eb2a4a1b1fe0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d90c8a36fff52f1c8c05b54d4ce79610431ec0
-----Decoded View---------------
Arg [0] : _stateAddress (address): 0x1f426C51F0Ef7655A6f4c3Eb58017d2F1c381bfF
Arg [1] : _coldStorageOwnerAddress (address): 0x51c5cE7C4926D5cA74f4824e11a062f1Ef491762
Arg [2] : _stakingContractAddress (address): 0xBaF121D02E6948D3A089F99dDc522eb2A4a1b1fE
Arg [3] : _escrowOpenOrderEnabled (bool): True
Arg [4] : _deployedTimestampOverride (uint256): 0
Arg [5] : _mintingLimiterAddress (address): 0x30D90c8a36FFF52F1C8C05b54d4CE79610431Ec0
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000001f426c51f0ef7655a6f4c3eb58017d2f1c381bff
Arg [1] : 00000000000000000000000051c5ce7c4926d5ca74f4824e11a062f1ef491762
Arg [2] : 000000000000000000000000baf121d02e6948d3a089f99ddc522eb2a4a1b1fe
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000030d90c8a36fff52f1c8c05b54d4ce79610431ec0
Deployed Bytecode Sourcemap
587:46089:10:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;587:46089:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13089:696;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;13089:696:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1186:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;6113:120;;;:::i;:::-;;;;-1:-1:-1;;;;;6113:120:10;;;;;;;;;;;;;;17086:2780;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;17086:2780:10;;;;;;;;;;;;;;;;;;;;;;:::i;996:25::-;;;:::i;:::-;;;;;;;;;;;;;;;;1298:81;;;:::i;21073:2386::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;21073:2386:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;42974:687::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42974:687:10;;:::i;23465:2317::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;23465:2317:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;1027:26::-;;;:::i;12459:624::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12459:624:10;;:::i;:::-;;;;-1:-1:-1;;;;;12459:624:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1098:82;;;:::i;26105:632::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;26105:632:10;;;;;;;;;;;;:::i;13791:379::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13791:379:10;;;;;;;:::i;:::-;;1482:137:11;;;:::i;5711:171:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5711:171:10;-1:-1:-1;;;;;5711:171:10;;:::i;43667:810::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;43667:810:10;;;;;;;;;;;;;;;;;;;:::i;5549:156::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5549:156:10;-1:-1:-1;;;;;5549:156:10;;:::i;682:77:11:-;;;:::i;1038:90::-;;;:::i;14176:242:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14176:242:10;;:::i;9220:3018::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;9220:3018:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;6239:121::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;6239:121:10;;;;:::i;262:21:11:-;;;:::i;20177:539:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20177:539:10;;;;;;-1:-1:-1;;;;;20177:539:10;;:::i;5888:219::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5888:219:10;-1:-1:-1;;;;;5888:219:10;;:::i;2498:184:11:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;2498:184:11;;;;;;;;:::i;1790:107::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1790:107:11;-1:-1:-1;;;;;1790:107:11;;:::i;1059:32:10:-;;;:::i;13089:696::-;13439:5;;:40;;;-1:-1:-1;;;13439:40:10;;-1:-1:-1;;;;;13439:40:10;;;;;;;;;;;;;;;13177:27;;;;;;;;;;;;13439:5;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;13439:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13439:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13439:40:10;13493:5;;:41;;;-1:-1:-1;;;13493:41:10;;-1:-1:-1;;;;;13493:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;13439:40;;13493:41;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;13493:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13493:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13493:41:10;13548:5;;:43;;;-1:-1:-1;;;13548:43:10;;-1:-1:-1;;;;;13548:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;13493:41;;13548:43;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;13548:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13548:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13548:43:10;13605:5;;:44;;;-1:-1:-1;;;13605:44:10;;-1:-1:-1;;;;;13605:44:10;;;;;;;;;;;;;;;:5;;;;;:24;;:44;;;;;13548:43;;13605:44;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;13605:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13605:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13605:44:10;13663:5;;:46;;;-1:-1:-1;;;13663:46:10;;-1:-1:-1;;;;;13663:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;13605:44;;13663:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;13663:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13663:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;13663:46:10;;;;;;;;;;;;;;;;13723:5;;;;;;;;;-1:-1:-1;;;;;13723:5:10;-1:-1:-1;;;;;13723:25:10;;13749:8;13758:9;13723:45;;;;;;;;;;;;;-1:-1:-1;;;;;13723:45:10;-1:-1:-1;;;;;13723:45:10;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13723:45:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13723:45:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13723:45:10;13419:359;;;;-1:-1:-1;13419:359:10;;-1:-1:-1;13419:359:10;-1:-1:-1;13419:359:10;-1:-1:-1;13723:45:10;;-1:-1:-1;13089:696:10;-1:-1:-1;;;13089:696:10:o;1186:34::-;;;-1:-1:-1;;;1186:34:10;;;;;:::o;6113:120::-;6202:5;;:24;;;-1:-1:-1;;;6202:24:10;;;;6161:22;;-1:-1:-1;;;;;6202:5:10;;:22;;:24;;;;;;;;;;;;;;:5;:24;;;5:2:-1;;;;30:1;27;20:12;5:2;6202:24:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6202:24:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;6202:24:10;;-1:-1:-1;6113:120:10;:::o;17086:2780::-;17316:22;17352:23;17389:24;17427:25;17466:27;17507:25;5016:5;;;;;;;;;-1:-1:-1;;;;;5016:5:10;-1:-1:-1;;;;;5016:23:10;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17596:1;17561:16;;;:6;:16;;;;;:23;-1:-1:-1;;;;;17561:23:10;17553:112;;;;-1:-1:-1;;;17553:112:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17698:1;17683:12;:16;17675:102;;;;-1:-1:-1;;;17675:102:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17811:13;17795:12;:29;;17787:127;;;;-1:-1:-1;;;17787:127:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17933:16;;;;:6;:16;;;;;;;;;:28;;;:43;;;17986:29;;;:45;;;18041:26;;;:43;;;18094:37;;;:61;;;-1:-1:-1;18348:5:10;;18370:25;;;18348:48;;-1:-1:-1;;;18348:48:10;;-1:-1:-1;18348:48:10;;;;;;;;-1:-1:-1;;;;;18348:5:10;;;;:21;;:48;;;;;17933:16;18348:48;;;;;:5;:48;;;5:2:-1;;;;30:1;27;20:12;5:2;18348:48:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18348:48:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18348:48:10;18345:219;;18421:35;18447:8;18421:25;:35::i;:::-;18527:16;;;;:6;:16;;;;;:25;;;18501:52;;:25;:52::i;:::-;18470:16;;;;:6;:16;;;;;:28;;:83;18345:219;18678:5;;;;18699:16;;;:6;:16;;;;;;;;;:23;;18724:25;;;18678:72;;-1:-1:-1;;;18678:72:10;;-1:-1:-1;;;;;18699:23:10;;;18678:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;18699:16;;18678:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;18678:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18678:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18678:72:10;18654:96;;18650:146;;;18766:19;18776:8;18766:9;:19::i;:::-;18811:23;18825:8;18811:13;:23::i;:::-;18849:16;;;;:6;:16;;;;;:31;;;;;18845:144;;;18896:25;18912:8;18896:15;:25::i;:::-;18845:144;;;18952:26;18969:8;18952:16;:26::i;:::-;18999:16;19018;;;:6;:16;;;;;;;;:23;;;19071:25;;;;-1:-1:-1;;;;;;19106:23:10;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;19106:23:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19144:344;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19018:23;19144:344;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19018:23:10;;;;19144:344;;;;;;;;;19520:5;;:40;;;-1:-1:-1;;;19520:40:10;;-1:-1:-1;;;;;19520:40:10;;;;;;;;;;;;;;;:5;;;;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;19520:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19520:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19520:40:10;19574:5;;:41;;;-1:-1:-1;;;19574:41:10;;-1:-1:-1;;;;;19574:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;19520:40;;19574:41;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;19574:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19574:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19574:41:10;19629:5;;:43;;;-1:-1:-1;;;19629:43:10;;-1:-1:-1;;;;;19629:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;19574:41;;19629:43;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;19629:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19629:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19629:43:10;19686:5;;:44;;;-1:-1:-1;;;19686:44:10;;-1:-1:-1;;;;;19686:44:10;;;;;;;;;;;;;;;:5;;;;;:24;;:44;;;;;19629:43;;19686:44;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;19686:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19686:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19686:44:10;19744:5;;:46;;;-1:-1:-1;;;19744:46:10;;-1:-1:-1;;;;;19744:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;19686:44;;19744:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;19744:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19744:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19744:46:10;19804:5;;:45;;;-1:-1:-1;;;19804:45:10;;-1:-1:-1;;;;;19804:45:10;;;;;;;;;;;;;;;:5;;;;;:25;;:45;;;;;19744:46;;19804:45;;;;;;;:5;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;19804:45:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19804:45:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19804:45:10;19499:360;;-1:-1:-1;19499:360:10;;-1:-1:-1;19499:360:10;;-1:-1:-1;19499:360:10;-1:-1:-1;19499:360:10;-1:-1:-1;19804:45:10;-1:-1:-1;;;17086:2780:10;;;;;;;;;;;:::o;996:25::-;;;;:::o;1298:81::-;;;-1:-1:-1;;;;;1298:81:10;;:::o;21073:2386::-;21363:19;21419:21;21477:24;985:5;21516:36;;21512:216;;;-1:-1:-1;985:5:10;21512:216;21741:14;21737:276;;-1:-1:-1;21905:12:10;;-1:-1:-1;21988:14:10;21737:276;22126:12;22039:83;22059:13;22074:16;22092:5;22099:22;22039:19;:83::i;:::-;:99;22022:1396;;22215:1;22201:15;;22022:1396;;;22367:67;985:5;22367:52;22386:31;985:5;22400:16;22386:31;:13;:31;:::i;:::-;22367:13;;:52;:17;:52;:::i;:::-;:56;:67;:56;:67;:::i;:::-;22353:81;-1:-1:-1;22462:66:10;22478:49;985:5;22478:34;:12;22495:16;22478:34;:16;:34;:::i;:49::-;22462:11;;:66;:15;:66;:::i;:::-;22448:80;-1:-1:-1;22555:4:10;22546:13;;;;22542:866;;;22795:67;22811:50;985:5;22811:35;:13;22829:16;22811:35;:17;:35;:::i;22795:67::-;22781:81;;22880:23;22906:80;22930:13;22945:16;22963:22;22906:23;:80::i;:::-;22880:106;;23027:11;23008:15;:30;23004:185;;23076:32;:11;23092:15;23076:32;:15;:32;:::i;:::-;23062:46;;23004:185;;;23169:1;23155:15;;23004:185;22542:866;;;;23328:65;23344:48;985:5;23344:33;:13;23362:14;23344:33;:17;:33;:::i;:48::-;23328:11;;:65;:15;:65;:::i;:::-;23314:79;;22542:866;-1:-1:-1;;21073:2386:10;;;;;;;;;:::o;42974:687::-;43040:25;43077:16;;;:6;:16;;;;;:36;;;:40;;;43131:30;;;:34;43127:232;;43240:16;;;;:6;:16;;;;;;;;:34;;;;43276:37;;;;43321:26;;;;;43220:128;;43240:34;43276:37;43315:4;;43220:19;:128::i;:::-;43181:16;;;;:6;:16;;;;;:36;;:167;43127:232;43406:1;43372:16;;;:6;:16;;;;;:31;;;:35;43368:234;;43482:16;;;;:6;:16;;;;;;;:34;;;;43518:37;;;;43564:26;;;;;43462:129;;43482:16;43462:19;:129::i;:::-;43423:16;;;;:6;:16;;;;;:36;;:168;43368:234;-1:-1:-1;43618:16:10;;;;:6;:16;;;;;:36;;;;42974:687::o;23465:2317::-;23754:19;23810:21;23868:24;985:5;23907:36;;23903:216;;;-1:-1:-1;985:5:10;23903:216;24132:14;24128:274;;-1:-1:-1;24294:12:10;;-1:-1:-1;24377:14:10;24128:274;24444:82;24464:13;24479:16;24497:4;24503:22;24444:19;:82::i;:::-;24428:12;:98;24411:1337;;24603:1;24589:15;;24411:1337;;;24649:65;985:5;24649:50;24667:31;:16;985:5;24667:31;:20;:31;:::i;24649:65::-;24635:79;-1:-1:-1;24862:68:10;24635:79;24863:49;985:5;24863:34;:12;24880:16;24863:34;:16;:34;:::i;:49::-;24862:55;:68;:55;:68;:::i;1027:26::-;;;;:::o;12459:624::-;12525:15;12774:16;;;:6;:16;;;;;:23;;;12811:25;;;12850:34;;;;12898:35;;;;12947:28;;;;12989:29;;;;13032:30;;;;;-1:-1:-1;;;;;12774:23:10;;;;12811:25;;12850:34;;12898:35;;12947:28;;12989:29;13032:30;12459:624::o;1098:82::-;;;-1:-1:-1;;;;;1098:82:10;;:::o;26105:632::-;26314:17;;26240:23;;26279:32;:22;26306:4;26279:32;:26;:32;:::i;:::-;:52;26275:135;;;26372:17;;:27;;26394:4;26372:27;:21;:27;:::i;:::-;26347:52;;26275:135;26437:50;26455:31;:16;985:5;26455:31;:20;:31;:::i;26437:50::-;26419:68;-1:-1:-1;26515:82:10;26535:61;26594:1;26536:52;26582:5;26536:41;26544:32;:22;26571:4;26544:32;:26;:32;:::i;:::-;26536:3;;:41;:7;:41;:::i;:52::-;26535:58;:61;:58;:61;:::i;:::-;26515:15;;:82;:19;:82;:::i;:::-;26497:100;;26625:73;985:5;26625:58;985:5;26625:43;26645:7;;;;;;;;;-1:-1:-1;;;;;26645:7:10;-1:-1:-1;;;;;26645:20:10;;:22;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26645:22:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;26645:22:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;26645:22:10;26625:15;;:43;:19;:43;:::i;:73::-;26607:91;26105:632;-1:-1:-1;;;;26105:632:10:o;13791:379::-;5016:5;;;;;;;;;-1:-1:-1;;;;;5016:5:10;-1:-1:-1;;;;;5016:23:10;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13890:5;;13921:21;;-1:-1:-1;;;;;13890:5:10;;;;:17;;13921:21;13956:9;13979:13;:3;13987:4;13979:13;:7;:13;:::i;:::-;13890:207;;;-1:-1:-1;;;;;;13890:207:10;;;;;;;-1:-1:-1;;;;;13890:207:10;;;;;;;;;;;;;;;;;;14006:1;13890:207;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14006:1;13890:207;;;;5:2:-1;;;;30:1;27;20:12;5:2;13890:207:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;14113:49:10;;;;;;;;;;;;;;;;-1:-1:-1;14113:49:10;;;;;;;;-1:-1:-1;14113:49:10;13791:379;;:::o;1482:137:11:-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;1580:1;1564:6;;1543:40;;-1:-1:-1;;;;;1564:6:11;;;;1543:40;;1580:1;;1543:40;1610:1;1593:19;;-1:-1:-1;;;;;;1593:19:11;;;1482:137::o;5711:171:10:-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;5790:7:10;:42;;-1:-1:-1;;;;;5790:42:10;;-1:-1:-1;;;;;;5790:42:10;;;;;;;;5847:28;;;;;;;;;;;;;;;;5711:171;:::o;43667:810::-;43817:25;43867:4;43858:13;;;;43854:583;;;43907:87;43972:21;43907:60;43930:36;43972:21;985:5;43930:36;:25;:36;:::i;:::-;43907:18;;:60;:22;:60;:::i;:87::-;43887:107;;44028:113;44050:90;44074:18;44094:21;44117:22;44050:23;:90::i;:::-;44028:17;;:113;:21;:113;:::i;:::-;44008:133;;43854:583;;;44192:87;44257:21;44192:60;44215:36;44257:21;985:5;44215:36;:25;:36;:::i;44192:87::-;44172:107;;44313:113;44335:90;44359:18;44379:21;44402:22;44335:23;:90::i;:::-;44313:17;;:113;:21;:113;:::i;:::-;44293:133;43667:810;-1:-1:-1;;;;;43667:810:10:o;5549:156::-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;5624:5:10;:35;;-1:-1:-1;;;;;5624:35:10;;-1:-1:-1;;;;;;5624:35:10;;;;;;;;5674:24;;;;;;;;;;;;;;;;5549:156;:::o;682:77:11:-;720:7;746:6;-1:-1:-1;;;;;746:6:11;682:77;:::o;1038:90::-;1078:4;1115:6;-1:-1:-1;;;;;1115:6:11;1101:10;:20;;1038:90::o;14176:242:10:-;14316:5;;14334:21;;14316:51;;;-1:-1:-1;;;14316:51:10;;-1:-1:-1;;;;;14334:21:10;;;14316:51;;;;;;;;;;;;14250:7;;;;14316:5;;:17;;:51;;;;;;;;;;;;;;:5;:51;;;5:2:-1;;;;30:1;27;20:12;5:2;14316:51:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;14316:51:10;;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;14316:51:10;;;;14176:242;-1:-1:-1;;;14176:242:10:o;9220:3018::-;5016:5;;:25;;;-1:-1:-1;;;5016:25:10;;;;9469:16;;-1:-1:-1;;;;;5016:5:10;;:23;;:25;;;;;;;;;;;;;;:5;:25;;;5:2:-1;;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;985:5;9518:14;:27;;9510:105;;;;-1:-1:-1;;;9510:105:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9651:5;;;;;;;;;-1:-1:-1;;;;;9651:5:10;-1:-1:-1;;;;;9651:24:10;;:26;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9651:26:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9651:26:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9651:26:10;9633:44;;;9625:119;;;;-1:-1:-1;;;9625:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9755:114;9791:8;9801:9;9812:18;9832:19;9853:15;9755:35;:114::i;:::-;9952:5;;;;;;;;;-1:-1:-1;;;;;9952:5:10;-1:-1:-1;;;;;9952:30:10;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9952:32:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9952:32:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9952:32:10;9913:5;;:35;;;-1:-1:-1;;;9913:35:10;;-1:-1:-1;;;;;9913:35:10;;;;;;;;;:5;;;;;:25;;:35;;;;;9952:32;;9913:35;;;;;;;:5;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;9913:35:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9913:35:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9913:35:10;:71;;;:137;;-1:-1:-1;10000:5:10;;:35;;;-1:-1:-1;;;10000:35:10;;-1:-1:-1;;;;;10000:35:10;;;;;;;;;10038:12;;10000:5;;;;;:25;;:35;;;;;;;;;;;;;;;:5;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;10000:35:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10000:35:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10000:35:10;:50;9913:137;9905:245;;;;-1:-1:-1;;;9905:245:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10271:23;;10268:532;;10313:15;10310:480;;;10401:5;;:41;;;-1:-1:-1;;;10401:41:10;;-1:-1:-1;;;;;10401:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;;;;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;10401:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10401:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10401:41:10;10379:63;;10371:171;;;;-1:-1:-1;;;10371:171:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10310:480;;;10635:5;;:40;;;-1:-1:-1;;;10635:40:10;;-1:-1:-1;;;;;10635:40:10;;;;;;;;;;;;;;;:5;;;;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;10635:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10635:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10635:40:10;10613:62;;10605:170;;;;-1:-1:-1;;;10605:170:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10810:5;;:35;;;-1:-1:-1;;;10810:35:10;;-1:-1:-1;;;;;10810:35:10;;;;;;;;;:5;;;;;:25;;:35;;;;;:5;;:35;;;;;;;:5;;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;10810:35:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10855:5:10;;:40;;;-1:-1:-1;;;10855:40:10;;-1:-1:-1;;;;;10855:40:10;;;;;;;;;:5;;;;;-1:-1:-1;10855:30:10;;-1:-1:-1;10855:40:10;;;;;:5;;:40;;;;;;;:5;;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;10855:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10855:40:10;;;;10905:10;;:12;;;;;;;;;;;;;10995:8;11021:12;11051:9;11078:18;11114:19;11151:15;11184:14;11216:10;;10961:283;;;;;;-1:-1:-1;;;;;10961:283:10;-1:-1:-1;;;;;10961:283:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;10961:283:10;;;10938:320;;;;;;10927:331;;11282:8;11268:11;:22;;;;11326:8;11300:6;:16;11307:8;11300:16;;;;;;;;;;;:23;;;:34;;;;;-1:-1:-1;;;;;11300:34:10;;;;;-1:-1:-1;;;;;11300:34:10;;;;;;11372:9;11344:6;:16;11351:8;11344:16;;;;;;;;;;;:25;;:37;;;;11428:18;11391:6;:16;11398:8;11391:16;;;;;;;;;;;:34;;:55;;;;11494:19;11456:6;:16;11463:8;11456:16;;;;;;;;;;;:35;;:57;;;;11557:15;11523:6;:16;11530:8;11523:16;;;;;;;;;;;:31;;;:49;;;;;;;;;;;;;;;;;;11615:14;11582:6;:16;11589:8;11582:16;;;;;;;;;;;:30;;:47;;;;11718:9;11696:8;-1:-1:-1;;;;;11644:215:10;;11674:8;11741:18;11773:19;11806:15;11835:14;11644:215;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12161:44;12175:8;12185:19;12161:13;:44::i;:::-;9220:3018;;;;;;;;:::o;6239:121::-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;6318:22:10;:35;;;;;-1:-1:-1;;;6318:35:10;-1:-1:-1;;;;6318:35:10;;;;;;;;;6239:121::o;262:21:11:-;;;-1:-1:-1;;;;;262:21:11;;:::o;20177:539:10:-;5016:5;;;;;;;;;-1:-1:-1;;;;;5016:5:10;-1:-1:-1;;;;;5016:23:10;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20282:16;;;;:6;:16;;;;;:23;-1:-1:-1;;;;;20270:35:10;;;20282:23;;20270:35;;:69;;;20321:18;:16;:18::i;:::-;-1:-1:-1;;;;;20309:30:10;:8;-1:-1:-1;;;;;20309:30:10;;20270:69;20262:149;;;;-1:-1:-1;;;20262:149:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20464:1;20429:16;;;:6;:16;;;;;:23;-1:-1:-1;;;;;20429:23:10;20421:110;;;;-1:-1:-1;;;20421:110:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20603:23;20617:8;20603:13;:23::i;:::-;20644:16;;;;:6;:16;;;;;;;;20637:23;;-1:-1:-1;;;;;;20637:23:10;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;20637:23:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20675:34;-1:-1:-1;;;;;20675:34:10;;;20651:8;;20675:34;;20644:16;20675:34;20177:539;;:::o;5888:219::-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;5981:14:10;:62;;-1:-1:-1;;;;;5981:62:10;;-1:-1:-1;;;;;;5981:62:10;;;;;;;;6058:42;;;;;;;;;;;;;;;;5888:219;:::o;2498:184:11:-;2595:13;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;2634:13;-1:-1:-1;;;;;2627:30:11;;2658:7;:5;:7::i;:::-;2667;2627:48;;;;;;;;;;;;;-1:-1:-1;;;;;2627:48:11;-1:-1:-1;;;;;2627:48:11;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2627:48:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2627:48:11;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2627:48:11;;-1:-1:-1;942:1:11;2498:184;;;;:::o;1790:107::-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;1862:28;1881:8;1862:18;:28::i;:::-;1790:107;:::o;1059:32:10:-;;;;:::o;8494:278::-;8608:16;;;;:6;:16;;;;;:23;;;8633:25;;;8660:34;;;;8696:35;;;;8733:31;;;;;8572:193;;-1:-1:-1;;;;;8608:23:10;;;;8696:35;8733:31;;8572:35;:193::i;14763:1753::-;14818:16;14837;;;:6;:16;;;;;;;;;:23;;;14890:25;;;;14957:37;;;;;15032:5;;:41;;-1:-1:-1;;;15032:41:10;;-1:-1:-1;;;;;14837:23:10;;;15032:41;;;;;;;;;;;;;;14890:25;;14957:37;;15032:5;;;;;:20;;:41;;;;;14837:16;;15032:41;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;15032:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15032:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15032:41:10;15008:65;;15004:1506;;;15093:5;;:39;;;-1:-1:-1;;;15093:39:10;;-1:-1:-1;;;;;15093:39:10;;;;;;;;;;;;;;;15135:1;;15093:5;;;;;:19;;:39;;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;15093:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15093:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15093:39:10;:43;15089:690;;;15156:5;;;15256:16;;;:6;:16;;;;;;;;:26;;;;15327:41;;-1:-1:-1;;;15327:41:10;;-1:-1:-1;;;;;15327:41:10;;;;;;;;;;;;;;;15156:5;;;;;:17;;15195:8;;15225:9;;15156:5;;;;15327:20;;:41;;;;;;;;;;15156:5;15327:41;;;5:2:-1;;;;30:1;27;20:12;5:2;15327:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15327:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15327:41:10;15156:313;;;-1:-1:-1;;;;;;15156:313:10;;;;;;;-1:-1:-1;;;;;15156:313:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15390:1;15156:313;;;;;;;;;;;;985:5;15156:313;;;;;;;;;;;;;;;;;;;;;;15390:1;15156:313;;;;5:2:-1;;;;30:1;27;20:12;5:2;15156:313:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;15619:16:10;;;;:6;:16;;;;;;;;;:26;;;;15667:28;;;;15717:29;;;;;15492:272;;15593:4;15492:272;;;;;;;;;;;;;;;;;;;;;;;;;15562:9;;-1:-1:-1;;;;;;15492:272:10;;;;;;;;;;;;;15089:690;15796:5;;:40;;;-1:-1:-1;;;15796:40:10;;-1:-1:-1;;;;;15796:40:10;;;;;;;;;;;;;;;15839:1;;15796:5;;;;;:20;;:40;;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;15796:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15796:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15796:40:10;:44;15792:708;;;15860:5;;;15960:16;;;:6;:16;;;;;;;;;:26;;;;16008:40;;-1:-1:-1;;;16008:40:10;;-1:-1:-1;;;;;16008:40:10;;;;;;;;;;;;;;;15860:5;;;;;:17;;15899:8;;15929:9;;15960:26;15860:5;;16008:19;;:40;;;;;15960:16;;16008:40;;;;;;15860:5;16008:40;;;5:2:-1;;;;30:1;27;20:12;5:2;16008:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16008:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16008:40:10;15860:329;;;-1:-1:-1;;;;;;15860:329:10;;;;;;;-1:-1:-1;;;;;15860:329:10;;;;;;;;;;;;;;;;;;;;;;;;;16070:1;15860:329;;;;;;;;;;;;;;;;;;985:5;15860:329;;;;;;;;;;;;;;;;;;;;;;16070:1;15860:329;;;;5:2:-1;;;;30:1;27;20:12;5:2;15860:329:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;16313:5:10;16340:16;;;:6;:16;;;;;;;;:26;;;;16388:28;;;;16438:29;;;;;16212:273;;;;;;;;;;;;;;;;;;;;;16282:9;;-1:-1:-1;;;;;;16212:273:10;;;;;;;;;;;;;15792:708;14763:1753;;;;:::o;6370:454::-;6547:1;6510:16;;;:6;:16;;;;;:34;;;:38;6507:311;;6605:21;6629:16;;;:6;:16;;;;;;:34;;;;;6677:38;;;;-1:-1:-1;6729:5:10;6744:22;;6768:23;;6729:78;;-1:-1:-1;;;6729:78:10;;-1:-1:-1;;;;;6744:22:10;;;6729:78;;;;6768:23;;;6729:78;;;;;;;;;;;;6629:34;;6729:5;;;:14;;:78;;;;;6605:21;;6729:78;;;;;6605:21;6729:5;:78;;;5:2:-1;;;;30:1;27;20:12;5:2;6729:78:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6729:78:10;;;;6507:311;6370:454;:::o;27199:1788::-;27301:1;27264:16;;;:6;:16;;;;;:34;;;:38;27260:695;;27516:5;;;;27537:16;;;:6;:16;;;;;;;;;:23;;27562:25;;;27516:72;;-1:-1:-1;;;27516:72:10;;-1:-1:-1;;;;;27537:23:10;;;27516:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;27537:16;;27516:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;27516:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;27516:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;27516:72:10;27478:16;;;;:6;27516:72;27478:16;;;;:34;;;:110;27474:471;;27697:16;;;;:6;:16;;;;;:34;;;;27661:33;;;;:70;27474:471;;;27858:5;;;;27879:16;;;:6;:16;;;;;;;;;:23;;27904:25;;;27858:72;;-1:-1:-1;;;27858:72:10;;-1:-1:-1;;;;;27879:23:10;;;27858:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;27879:16;;27858:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;27858:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;27858:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;27858:72:10;27822:16;;;;:6;27858:72;27822:16;;;;:33;;:108;27474:471;28146:5;;;;28167:16;;;:6;:16;;;;;;;;;:23;;28192:25;;;28146:72;;-1:-1:-1;;;28146:72:10;;-1:-1:-1;;;;;28167:23:10;;;28146:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;28167:16;;28146:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;28146:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;28146:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28146:72:10;28109:16;;;;:6;28146:72;28109:16;;;;:33;;;:109;:165;;;;-1:-1:-1;28273:1:10;28235:16;;;:6;:16;;;;;:35;;;:39;;28109:165;28093:645;;;28427:16;;;;:6;:16;;;;;:28;;;;28477:30;;;;28604:29;;;;;28334:393;;28391:335;;28477:30;28529:3;;28427:28;;28604:29;28477:30;;28391:14;:335::i;:::-;28334:16;;;;:6;:16;;;;;:35;;;;:393;:39;:393;:::i;:::-;28299:16;;;;:6;:16;;;;;:32;;:428;28093:645;28839:1;28803:16;;;:6;:16;;;;;:33;;;:37;28799:88;;28856:20;28867:8;28856:10;:20::i;:::-;28935:1;28900:16;;;:6;:16;;;;;:32;;;:36;28896:85;;28952:18;28961:8;28952;:18::i;29450:1685::-;29553:1;29516:16;;;:6;:16;;;;;:34;;;:38;29512:688;;29767:5;;;;29787:16;;;:6;:16;;;;;;;;;:23;;29812:25;;;29767:71;;-1:-1:-1;;;29767:71:10;;-1:-1:-1;;;;;29787:23:10;;;29767:71;;;;;;;;;;;;;:5;;;;;:19;;:71;;;;;29787:16;;29767:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;29767:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29767:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29767:71:10;29729:16;;;;:6;29767:71;29729:16;;;;:34;;;:109;29725:465;;29945:16;;;;:6;:16;;;;;:34;;;;29910:32;;;;:69;29725:465;;;30104:5;;;;30124:16;;;:6;:16;;;;;;;;;:23;;30149:25;;;30104:71;;-1:-1:-1;;;30104:71:10;;-1:-1:-1;;;;;30124:23:10;;;30104:71;;;;;;;;;;;;;:5;;;;;:19;;:71;;;;;30124:16;;30104:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;30104:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30104:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30104:71:10;30069:16;;;;:6;30104:71;30069:16;;;;:32;;:106;29725:465;30262:5;;;;30282:16;;;:6;:16;;;;;;;;;:23;;30307:25;;;30262:71;;-1:-1:-1;;;30262:71:10;;-1:-1:-1;;;;;30282:23:10;;;30262:71;;;;;;;;;;;;;:5;;;;;:19;;:71;;;;;30282:16;;30262:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;30262:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30262:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30262:71:10;30226:16;;;;:6;30262:71;30226:16;;;;:32;;;:107;:163;;;;-1:-1:-1;30388:1:10;30350:16;;;:6;:16;;;;;:35;;;:39;;30226:163;30210:677;;;30548:16;;;;:6;:16;;;;;:28;;;;30602:30;;;;30741:29;;;;;30446:430;;30507:368;;30602:30;30658:3;;30548:28;;30741:29;30602:30;;30507:15;:368::i;30446:430::-;30410:16;;;;:6;:16;;;;;:33;;:466;30210:677;30986:1;30951:16;;;:6;:16;;;;;:32;;;:36;30947:86;;31003:19;31013:8;31003:9;:19::i;:::-;31082:1;31046:16;;;:6;:16;;;;;:33;;;:37;31042:87;;31099:19;31109:8;31099:9;:19::i;834:176:12:-;892:7;923:5;;;946:6;;;;938:46;;;;;-1:-1:-1;;;938:46:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;834:176;-1:-1:-1;;;834:176:12:o;2159:459::-;2217:7;2458:6;2454:45;;-1:-1:-1;2487:1:12;2480:8;;2454:45;2521:5;;;2525:1;2521;:5;:1;2544:5;;;;;:10;2536:56;;;;-1:-1:-1;;;2536:56:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3073:130;3131:7;3157:39;3161:1;3164;3157:39;;;;;;;;;;;;;;;;;:3;:39::i;1274:134::-;1332:7;1358:43;1362:1;1365;1358:43;;;;;;;;;;;;;;;;;:3;:43::i;7136:1312:10:-;7368:23;;7365:1077;;7415:5;;:32;;;-1:-1:-1;;;7415:32:10;;;;;;;;;;-1:-1:-1;;;;;7415:5:10;;;;:21;;:32;;;;;;;;;;;;;;;:5;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;7415:32:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7415:32:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;7415:32:10;:40;;7451:4;7415:40;7407:125;;;;-1:-1:-1;;;7407:125:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7365:1077;;;7734:5;;:32;;;-1:-1:-1;;;7734:32:10;;;;;;;;;;-1:-1:-1;;;;;7734:5:10;;;;:21;;:32;;;;;;;;;;;;;;;:5;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;7734:32:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7734:32:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;7734:32:10;7731:701;;7842:1;7803:36;7829:9;7803:25;:36::i;:::-;:40;7795:143;;;;-1:-1:-1;;;7795:143:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7959:15;7956:462;;;8055:5;;:41;;;-1:-1:-1;;;8055:41:10;;-1:-1:-1;;;;;8055:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;;;;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;8055:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8055:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;8055:41:10;8033:63;;8025:150;;;;-1:-1:-1;;;8025:150:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7956:462;8280:5;;:40;;;-1:-1:-1;;;8280:40:10;;-1:-1:-1;;;;;8280:40:10;;;;;;;;;;;;;;;:5;;;;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;8280:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8280:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;8280:40:10;8258:62;;8250:149;;;;-1:-1:-1;;;8250:149:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7136:1312;;;;;:::o;6830:299::-;6914:22;;-1:-1:-1;;;6914:22:10;;;;:42;;;;;6955:1;6940:12;:16;6914:42;6911:212;;;6972:5;;;6987:16;;;:6;:16;;;;;;:23;7012:22;;6972:77;;-1:-1:-1;;;6972:77:10;;-1:-1:-1;;;;;6987:23:10;;;6972:77;;;;7012:22;;;6972:77;;;;;;;;;;;;:5;;;:14;;:77;;;;;:5;;:77;;;;;;:5;;:77;;;5:2:-1;;;;30:1;27;20:12;5:2;6972:77:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;7063:16:10;;;;:6;:16;;;;;:34;;:49;;;-1:-1:-1;6911:212:10;6830:299;;:::o;2041:227:11:-;-1:-1:-1;;;;;2114:22:11;;2106:75;;;;-1:-1:-1;;;2106:75:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2217:6;;;2196:38;;-1:-1:-1;;;;;2196:38:11;;;;2217:6;;;2196:38;;;2244:6;:17;;-1:-1:-1;;;;;;2244:17:11;-1:-1:-1;;;;;2244:17:11;;;;;;;;;;2041:227::o;38161:1555:10:-;38217:15;38235:16;;;:6;:16;;;;;;;;:23;;;38288:25;;;;38491:33;;;;;38446:5;;:40;;-1:-1:-1;;;38446:40:10;;-1:-1:-1;;;;;38235:23:10;;;38446:40;;;;;;;;;;;;;;38235:23;;38288:25;;38217:15;;;;;;;;38446:79;;38491:33;;38446:5;;;:20;;:40;;;;;38235:16;;38446:40;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;38446:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38446:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38446:40:10;;:79;:44;:79;:::i;:::-;38420:105;;38535:18;38556:28;38575:8;38556:18;:28::i;:::-;38644:5;;:40;;;-1:-1:-1;;;38644:40:10;;-1:-1:-1;;;;;38644:40:10;;;;;;;;;;;;;;;38535:49;;-1:-1:-1;38644:5:10;;;:20;;:40;;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;38644:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38644:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38644:40:10;38607:16;;;;:6;38644:40;38607:16;;;;:33;;;:77;38603:615;;;38716:1;38700:17;;38748:1;38731:18;;985:5;38760:28;;38603:615;;;38835:5;;:43;;;-1:-1:-1;;;38835:43:10;;-1:-1:-1;;;;;38835:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;38835:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38835:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38835:43:10;38906:5;;:44;;;-1:-1:-1;;;38906:44:10;;-1:-1:-1;;;;;38906:44:10;;;;;;;;;;;;;;;38835:43;;-1:-1:-1;38906:5:10;;;:24;;:44;;;;;38835:43;;38906:44;;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;38906:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38906:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38906:44:10;38980:5;;:46;;;-1:-1:-1;;;38980:46:10;;-1:-1:-1;;;;;38980:46:10;;;;;;;;;;;;;;;38906:44;;-1:-1:-1;38980:5:10;;;:26;;:46;;;;;38906:44;;38980:46;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;38980:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38980:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38980:46:10;;-1:-1:-1;39163:44:10;39198:8;39163:34;:44::i;:::-;39259:1;39228:16;;;:6;:16;;;;;;;;:28;;;:32;;;;39270:26;;;:39;;;39352:5;;;39372:23;;39397:25;;;;;39352:71;;-1:-1:-1;;;39352:71:10;;-1:-1:-1;;;;;39372:23:10;;;39352:71;;;;;;;;;;;;;:5;;;:19;;:71;;;;;39228:16;;39352:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;39352:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;39352:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;39352:71:10;39319:16;;;;:6;39352:71;39319:16;;;;:30;;;:104;;;;39433:31;;;:49;;;39492:34;;;:50;;;39552:35;;;:52;;;39614:37;;:56;;;39681:28;39326:8;39681:18;:28::i;:::-;38161:1555;;;;;;;;:::o;31499:2848::-;31553:15;31571:16;;;:6;:16;;;;;;;;:23;;;31624:25;;;;32062:5;;:46;;-1:-1:-1;;;32062:46:10;;-1:-1:-1;;;;;31571:23:10;;;32062:46;;;;;;;;;;;;;;31571:23;;31624:25;;31553:15;;;;;;32062:5;;;;:26;;:46;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;32062:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32062:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32062:46:10;;-1:-1:-1;985:5:10;32122:29;;32118:89;;;-1:-1:-1;985:5:10;32118:89;32236:32;:17;985:5;32236:32;:21;:32;:::i;:::-;32369:16;;;;:6;:16;;;;;;;;;:28;;;32320:5;;:43;;-1:-1:-1;;;32320:43:10;;-1:-1:-1;;;;;32320:43:10;;;;;;;;;;;;;;;32216:52;;-1:-1:-1;32298:100:10;;32369:28;;32298:66;;32320:5;;;:23;;:43;;;;;32369:16;;32320:43;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;32320:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32320:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32320:43:10;32298:17;;:66;:21;:66;:::i;:100::-;32412:5;;:46;;;-1:-1:-1;;;32412:46:10;;-1:-1:-1;;;;;32412:46:10;;;;;;;;;;;;;;;32278:120;;-1:-1:-1;32278:120:10;;32412:5;;;;;:26;;:46;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;32412:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32412:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32412:46:10;:66;32408:238;;;32514:5;;:46;;;-1:-1:-1;;;32514:46:10;;-1:-1:-1;;;;;32514:46:10;;;;;;;;;;;;;;;:69;;32565:17;;32514:5;;:26;;:46;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;32514:69:10;32494:89;;32408:238;;;-1:-1:-1;32634:1:10;32408:238;32708:5;;:39;;;-1:-1:-1;;;32708:39:10;;-1:-1:-1;;;;;32708:39:10;;;;;;;;;;;;;;;32656:27;;32686:77;;985:5;;32686:62;;32708:5;;;;;:19;;:39;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;32708:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32708:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32708:39:10;32686:17;;:62;:21;:62;:::i;:77::-;32892:5;;:46;;;-1:-1:-1;;;32892:46:10;;-1:-1:-1;;;;;32892:46:10;;;;;;;;;;;;;;;32656:107;;-1:-1:-1;32892:71:10;;32656:107;;32892:5;;;;;:26;;:46;;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;32892:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32892:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32892:46:10;;:71;:50;:71;:::i;:::-;33048:16;;;;:6;:16;;;;;:32;;;;33013:30;;;;;32873:90;;-1:-1:-1;32992:90:10;;33013:68;;;:34;:68;:::i;32992:90::-;33156:16;;;;:6;:16;;;;;:32;;;32973:109;;-1:-1:-1;33111:79:10;;33132:57;;:19;;:57;:23;:57;:::i;:::-;33111:16;;:79;:20;:79;:::i;:::-;33362:5;;:39;;;-1:-1:-1;;;33362:39:10;;-1:-1:-1;;;;;33362:39:10;;;;;;;;;;;;;;;33092:98;;-1:-1:-1;33313:89:10;;33362:5;;;;;:19;;:39;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;33362:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;33362:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;33362:39:10;33313:5;;:44;;;-1:-1:-1;;;33313:44:10;;-1:-1:-1;;;;;33313:44:10;;;;;;;;;;;;;;;:5;;;;;:24;;:44;;;;;33362:39;;33313:44;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;33313:89:10;33482:16;;;;:6;:16;;;;;:32;;;;33448:29;;;;;33296:106;;-1:-1:-1;33429:87:10;;33448:67;;;:33;:67;:::i;:::-;33429:14;;:87;:18;:87;:::i;:::-;33586:16;;;;:6;:16;;;;;:32;;;33412:104;;-1:-1:-1;33543:77:10;;33562:57;;:19;;:57;:23;:57;:::i;:::-;33543:14;;:77;:18;:77;:::i;:::-;33818:16;;;;:6;:16;;;;;:30;;;;33783:29;;;;33746:32;;;;;33526:94;;-1:-1:-1;33662:212:10;;33746:118;;985:5;;33746:103;;33818:30;;33746:67;;:32;:67;:36;:67;:::i;:::-;:71;:103;:71;:103;:::i;:118::-;33699:16;;;;:6;:16;;;;;:28;;;;33662:32;;;;;:66;;;:36;:66;:::i;:212::-;33631:16;;;;:6;:16;;;;;:28;;;:243;;;;33884:26;;;:30;33981:32;;;33957:57;;:19;;:57;:23;:57;:::i;:::-;33924:16;;;;:6;:16;;;;;;;;;:30;;:90;;;;34058:5;;:40;;-1:-1:-1;;;34058:40:10;;-1:-1:-1;;;;;34058:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;34058:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;34058:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;34058:40:10;34024:16;;;;:6;34058:40;34024:16;;;;:31;;;:74;;;;34145:28;;;;34108:34;;;:65;34183:35;;;:52;;;34245:37;;:56;;;34312:28;34031:8;34312:18;:28::i;:::-;31499:2848;;;;;;;:::o;34632:1390::-;34687:15;34705:16;;;:6;:16;;;;;;;;:23;;;34758:25;;;;34863:32;;;;;34819:5;;:39;;-1:-1:-1;;;34819:39:10;;-1:-1:-1;;;;;34705:23:10;;;34819:39;;;;;;;;;;;;;;34705:23;;34758:25;;34687:15;;34819:77;;34863:32;;34819:5;;;;:19;;:39;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;34819:77:10;34793:103;;34906:18;34927:28;34946:8;34927:18;:28::i;:::-;35103:5;;:39;;;-1:-1:-1;;;35103:39:10;;-1:-1:-1;;;;;35103:39:10;;;;;;;;;;;;;;;34906:49;;-1:-1:-1;34965:21:10;;;;;;35103:5;;:19;;:39;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;35103:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35103:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35103:39:10;35067:16;;;;:6;35103:39;35067:16;;;;:32;;;:75;35063:493;;;-1:-1:-1;35174:1:10;;-1:-1:-1;35174:1:10;;-1:-1:-1;985:5:10;35063:493;;;35296:5;;:43;;;-1:-1:-1;;;35296:43:10;;-1:-1:-1;;;;;35296:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;35296:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35296:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35296:43:10;35367:5;;:44;;;-1:-1:-1;;;35367:44:10;;-1:-1:-1;;;;;35367:44:10;;;;;;;;;;;;;;;35296:43;;-1:-1:-1;35367:5:10;;;:24;;:44;;;;;35296:43;;35367:44;;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;35367:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35367:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35367:44:10;35441:5;;:46;;;-1:-1:-1;;;35441:46:10;;-1:-1:-1;;;;;35441:46:10;;;;;;;;;;;;;;;35367:44;;-1:-1:-1;35441:5:10;;;:26;;:46;;;;;35367:44;;35441:46;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;35441:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35441:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35441:46:10;;-1:-1:-1;35501:44:10;35536:8;35501:34;:44::i;:::-;35597:1;35566:16;;;:6;:16;;;;;;;;:28;;;:32;;;;35608:26;;;:39;;;35657:30;;;;:47;;;35748:5;;:40;;-1:-1:-1;;;35748:40:10;;-1:-1:-1;;;;;35748:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;35566:16;;35748:40;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;35748:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35748:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35748:40:10;35714:16;;;;:6;35748:40;35714:16;;;;:31;;;:74;;;;35798:34;;;:50;;;35858:35;;;:52;;;35920:37;;:56;;;35987:28;35721:8;35987:18;:28::i;40082:2886::-;40137:15;40155:16;;;:6;:16;;;;;;;;:23;;;40208:25;;;;40659:5;;:46;;-1:-1:-1;;;40659:46:10;;-1:-1:-1;;;;;40155:23:10;;;40659:46;;;;;;;;;;;;;;40155:23;;40208:25;;40137:15;;;;;;40659:5;;;;:26;;:46;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;40659:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;40659:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40659:46:10;;-1:-1:-1;985:5:10;40719:30;;40715:91;;;-1:-1:-1;985:5:10;40715:91;40836:33;:18;985:5;40836:33;:22;:33;:::i;:::-;40972:16;;;;:6;:16;;;;;;;;;:28;;;40923:5;;:43;;-1:-1:-1;;;40923:43:10;;-1:-1:-1;;;;;40923:43:10;;;;;;;;;;;;;;;40815:54;;-1:-1:-1;40900:101:10;;40972:28;;40900:67;;40923:5;;;:23;;:43;;;;;40972:16;;40923:43;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;40900:101:10;41015:5;;:46;;;-1:-1:-1;;;41015:46:10;;-1:-1:-1;;;;;41015:46:10;;;;;;;;;;;;;;;40879:122;;-1:-1:-1;40879:122:10;;41015:5;;;;;:26;;:46;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;41015:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41015:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41015:46:10;:67;41011:242;;;41142:5;;:46;;;-1:-1:-1;;;41142:46:10;;-1:-1:-1;;;;;41142:46:10;;;;;;;;;;;;;;;41119:70;;41142:5;;;;;:26;;:46;;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;41142:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41142:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41142:46:10;41119:18;;:70;:22;:70;:::i;:::-;41098:91;;41011:242;;;-1:-1:-1;41241:1:10;41011:242;41317:5;;:40;;;-1:-1:-1;;;41317:40:10;;-1:-1:-1;;;;;41317:40:10;;;;;;;;;;;;;;;41263:28;;41294:79;;985:5;;41294:64;;41317:5;;;;;:20;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;41294:79:10;41502:5;;:46;;;-1:-1:-1;;;41502:46:10;;-1:-1:-1;;;;;41502:46:10;;;;;;;;;;;;;;;41263:110;;-1:-1:-1;41502:72:10;;41263:110;;41502:5;;;;;:26;;:46;;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;41502:72:10;41659:16;;;;:6;:16;;;;;:33;;;;41624:30;;;;;41483:91;;-1:-1:-1;41603:91:10;;41624:69;;;:34;:69;:::i;41603:91::-;41769:16;;;;:6;:16;;;;;:33;;;41584:110;;-1:-1:-1;41723:81:10;;41744:59;;:20;;:59;:24;:59;:::i;41723:81::-;41976:5;;:40;;;-1:-1:-1;;;41976:40:10;;-1:-1:-1;;;;;41976:40:10;;;;;;;;;;;;;;;41704:100;;-1:-1:-1;41927:90:10;;41976:5;;;;;:20;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;41927:90:10;42097:16;;;;:6;:16;;;;;:33;;;;42063:29;;;;;41910:107;;-1:-1:-1;42044:88:10;;42063:68;;;:33;:68;:::i;42044:88::-;42203:16;;;;:6;:16;;;;;:33;;;42027:105;;-1:-1:-1;42159:79:10;;42178:59;;:20;;:59;:24;:59;:::i;42159:79::-;42438:16;;;;:6;:16;;;;;:30;;;;42403:29;;;;42365:33;;;;;42142:96;;-1:-1:-1;42280:214:10;;42365:119;;985:5;;42365:104;;42438:30;;42365:68;;:33;:68;:37;:68;:::i;:119::-;42318:16;;;;:6;:16;;;;;:28;;;;42280:33;;;;;:67;;;:37;:67;:::i;:214::-;42249:16;;;;:6;:16;;;;;;;;:28;;;:245;;;;42504:26;;;;:30;;;;42577:5;;:39;;-1:-1:-1;;;42577:39:10;;-1:-1:-1;;;;;42577:39:10;;;;;;;;;;;;;;;:5;;;;;:19;;:39;;;;;42249:16;;42577:39;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;42577:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;42577:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42577:39:10;42544:16;;;;:6;42577:39;42544:16;;;;:30;;;:72;;;;42685:33;;;42660:59;;:20;;:59;:24;:59;:::i;:::-;42626:16;;;;:6;:16;;;;;:31;;;:93;;;;42766:28;;;;42729:34;;;:65;42804:35;;;:52;;;42866:37;;:56;;;42933:28;42633:8;42933:18;:28::i;3718:338:12:-;3804:7;3904:12;3897:5;3889:28;;;;-1:-1:-1;;;3889:28:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;3889:28:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3927:9;3943:1;3939;:5;;;;;;;3718:338;-1:-1:-1;;;;;3718:338:12:o;1732:187::-;1818:7;1853:12;1845:6;;;;1837:29;;;;-1:-1:-1;;;1837:29:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;1837:29:12;-1:-1:-1;;;1888:5:12;;;1732:187::o;36754:1401:10:-;36822:18;36870:16;;;:6;:16;;;;;:23;;;36923:25;;;36992:31;;;;;-1:-1:-1;;;;;36870:23:10;;;;36923:25;36822:18;;36992:31;;36988:1116;;37094:16;;;;:6;:16;;;;;;;;;:32;;;37186:5;;:43;;-1:-1:-1;;;37186:43:10;;-1:-1:-1;;;;;37186:43:10;;;;;;;;;;;;;;;37094:32;;-1:-1:-1;37154:390:10;;37186:5;;;;:23;;:43;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;37186:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37186:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37186:43:10;37247:5;;:46;;;-1:-1:-1;;;37247:46:10;;-1:-1:-1;;;;;37247:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;37186:43;;37247:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;37247:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37247:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37247:46:10;37311:5;;:40;;;-1:-1:-1;;;37311:40:10;;-1:-1:-1;;;;;37311:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;37247:46;;37311:40;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;37311:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37311:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37311:40:10;37369:16;;;;:6;37311:40;37369:16;;;;;;;;:28;;;;37415:29;;;;;37462:5;;:46;;-1:-1:-1;;;37462:46:10;;-1:-1:-1;;;;;37462:46:10;;;;;;;;;;;;;;;37369:28;;37415:29;;37462:5;;;;;:26;;:46;;;;;37311:40;;37462:46;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;37462:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37462:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37462:46:10;37526:4;37154:14;:390::i;:::-;37140:404;;36988:1116;;;37641:16;;;;:6;:16;;;;;;;;;:33;;;37735:5;;:43;;-1:-1:-1;;;37735:43:10;;-1:-1:-1;;;;;37735:43:10;;;;;;;;;;;;;;;37641:33;;-1:-1:-1;37702:391:10;;37735:5;;;;:23;;:43;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;37735:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37735:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37735:43:10;37796:5;;:46;;;-1:-1:-1;;;37796:46:10;;-1:-1:-1;;;;;37796:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;37735:43;;37796:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;37796:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37796:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37796:46:10;37860:5;;:40;;;-1:-1:-1;;;37860:40:10;;-1:-1:-1;;;;;37860:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;37796:46;;37860:40;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;37860:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37860:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37860:40:10;37918:16;;;;:6;37860:40;37918:16;;;;;;;;:28;;;;37964:29;;;;;38011:5;;:46;;-1:-1:-1;;;38011:46:10;;-1:-1:-1;;;;;38011:46:10;;;;;;;;;;;;;;;37918:28;;37964:29;;38011:5;;;;;:26;;:46;;;;;37860:40;;38011:46;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;38011:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38011:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38011:46:10;38075:4;37702:15;:391::i;:::-;37688:405;;36988:1116;38120:27;:10;38135:11;38120:27;:14;:27;:::i;36109:362::-;36186:14;36203:16;;;:6;:16;;;;;;;;:23;;;36251:25;;;;36301:5;;:38;;-1:-1:-1;;;36301:38:10;;-1:-1:-1;;;;;36203:23:10;;;36301:38;;;;;;;;;;;;;;36203:23;;36251:25;;36186:14;;36301:5;;;;;:20;;:38;;;;;;;;;;:5;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;36301:38:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;36301:38:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;36301:38:10;36382:16;;;;:6;36301:38;36382:16;;;;;;;;:26;;;;36350:72;;;;;;;;;;;;;;;;;36301:38;;-1:-1:-1;36350:72:10;;;;;;;;;;36428:16;;;;:6;:16;;;;;;;;:26;;;:40;;;;-1:-1:-1;;36109:362:10:o;44781:1893::-;44929:16;;;;:6;:16;;;;;;;;;:28;;;;44898:26;;;;44853:5;;44869:23;;44853:40;;-1:-1:-1;;;44853:40:10;;-1:-1:-1;;;;;44869:23:10;;;44853:40;;;;;;44929:28;;44853:72;;44898:26;;44853:5;;;;;:15;;:40;;;;;44929:16;;44853:40;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;44853:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44853:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;44853:40:10;;:72;:44;:72;:::i;:::-;:104;;44845:156;;;;-1:-1:-1;;;44845:156:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45011:33;45035:8;45011:23;:33::i;:::-;-1:-1:-1;45128:16:10;;;;:6;:16;;;;;:28;;;;45099:26;;;;;:57;45095:329;;;45203:16;;;;:6;:16;;;;;:28;;;;45172:26;;;;;:60;;;:30;:60;:::i;:::-;-1:-1:-1;45277:1:10;45246:16;;;:6;:16;;;;;:28;;:32;45095:329;;;45342:16;;;;:6;:16;;;;;:26;;;;45309:28;;;;;:60;;;:32;:60;:::i;:::-;-1:-1:-1;45412:1:10;45383:16;;;:6;:16;;;;;:26;;:30;45095:329;45466:1;45437:16;;;:6;:16;;;;;:26;;;:30;45433:133;;45483:14;;;45503:16;;;:6;:16;;;;;;:23;;45528:26;;;;;45483:72;;-1:-1:-1;;;45483:72:10;;-1:-1:-1;;;;;45503:23:10;;;45483:72;;;;;;;;;;;;;:14;;;:19;;:72;;;;;:14;;:72;;;;;;:14;;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;45483:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45483:72:10;;;;45433:133;45610:1;45579:16;;;:6;:16;;;;;:28;;;:32;45575:128;;45627:5;;;45638:16;;;:6;:16;;;;;;:23;;45663:28;;;;;45627:65;;-1:-1:-1;;;45627:65:10;;-1:-1:-1;;;;;45638:23:10;;;45627:65;;;;;;;;;;;;;:5;;;:10;;:65;;;;;:5;;:65;;;;;;:5;;:65;;;5:2:-1;;;;30:1;27;20:12;5:2;45627:65:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45627:65:10;;;;45575:128;45712:5;;;;45743:16;;;:6;:16;;;;;;;;:23;;45780:25;;;;45819:26;;;;45859:30;;;;45903:31;;;;45948:34;;;;45996:35;;;;46045:37;;;;46096:36;;;;;45712:430;;-1:-1:-1;;;45712:430:10;;-1:-1:-1;;;;;45743:23:10;;;45712:430;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;;;;;:17;;:430;;;;;:5;:430;;;;;;:5;;:430;;;5:2:-1;;;;30:1;27;20:12;5:2;45712:430:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;46186:16:10;;;;:6;:16;;;;;;;;;:23;;;46223:25;;;46262:26;;;;46302:30;;;;46346:31;;;;46391:34;;;;46439:35;;;;46488:37;;;;46539:36;;;;46589:26;;;;46629:28;;;;;46157:510;;-1:-1:-1;;;;;46186:23:10;;;46157:510;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46186:23;46157:510;;;;;;;;;;;;;;;;;;-1:-1:-1;46157:510:10;;;;;;;;44781:1893;:::o
Swarm Source
bzzr://cb9a00bd74f3aa4fa52897b6a4e7577ae149655caffe63aac6692578ab03023a
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.