Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 2,308 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Approve | 23607487 | 94 days ago | IN | 0 ETH | 0.00000284 | ||||
| Approve | 23607228 | 94 days ago | IN | 0 ETH | 0.0000042 | ||||
| Grant Access | 22517494 | 246 days ago | IN | 0 ETH | 0.00016877 | ||||
| Set Total On Oth... | 22422007 | 260 days ago | IN | 0 ETH | 0.00002135 | ||||
| Set Total On Oth... | 22414865 | 261 days ago | IN | 0 ETH | 0.00001426 | ||||
| Set Total On Oth... | 22407735 | 262 days ago | IN | 0 ETH | 0.00001456 | ||||
| Set Total On Oth... | 22400583 | 263 days ago | IN | 0 ETH | 0.00002013 | ||||
| Set Total On Oth... | 22393464 | 264 days ago | IN | 0 ETH | 0.00002109 | ||||
| Set Total On Oth... | 22386339 | 265 days ago | IN | 0 ETH | 0.00003585 | ||||
| Set Total On Oth... | 22379192 | 266 days ago | IN | 0 ETH | 0.00002712 | ||||
| Set Total On Oth... | 22372041 | 267 days ago | IN | 0 ETH | 0.00002072 | ||||
| Set Total On Oth... | 22364908 | 268 days ago | IN | 0 ETH | 0.00001517 | ||||
| Set Total On Oth... | 22357709 | 269 days ago | IN | 0 ETH | 0.00002035 | ||||
| Set Total On Oth... | 22350532 | 270 days ago | IN | 0 ETH | 0.00002099 | ||||
| Set Total On Oth... | 22343354 | 271 days ago | IN | 0 ETH | 0.00003008 | ||||
| Set Total On Oth... | 22336199 | 272 days ago | IN | 0 ETH | 0.00002451 | ||||
| Set Total On Oth... | 22329031 | 273 days ago | IN | 0 ETH | 0.00003521 | ||||
| Set Total On Oth... | 22321862 | 274 days ago | IN | 0 ETH | 0.00001279 | ||||
| Set Total On Oth... | 22314696 | 275 days ago | IN | 0 ETH | 0.00001936 | ||||
| Set Total On Oth... | 22307537 | 276 days ago | IN | 0 ETH | 0.00001562 | ||||
| Set Total On Oth... | 22300375 | 277 days ago | IN | 0 ETH | 0.00001337 | ||||
| Set Total On Oth... | 22293206 | 278 days ago | IN | 0 ETH | 0.0000196 | ||||
| Set Total On Oth... | 22286040 | 279 days ago | IN | 0 ETH | 0.00001813 | ||||
| Set Total On Oth... | 22278874 | 280 days ago | IN | 0 ETH | 0.00001855 | ||||
| Set Total On Oth... | 22271727 | 281 days ago | IN | 0 ETH | 0.00001469 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MorpherState
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 "./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 {
require(getCanTransfer(msg.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);
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 onlyOwner {
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 onlyOwner {
stateAccess[_address] = true;
emit StateAccessGranted(_address, block.number);
}
function denyAccess(address _address) public onlyOwner {
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 onlyOwner {
transferAllowed[_address] = true;
emit TransfersEnabled(_address);
}
function disableTransfers(address _address) public onlyOwner {
transferAllowed[_address] = false;
emit TransfersDisabled(_address);
}
function getCanTransfer(address _address) public view returns(bool _hasAccess) {
return transferAllowed[_address];
}
// ----------------------------------------------------------------------------
// Minting/burning/transfer of token
// ----------------------------------------------------------------------------
function transfer(address _from, address _to, uint256 _token) public onlyPlatform notPaused {
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 onlyOwner {
morpherGovernance = _newGovernanceContractAddress;
emit GovernanceChange(_newGovernanceContractAddress);
}
function getGovernance() public view returns (address _governanceContract) {
return morpherGovernance;
}
function setMorpherBridge(address _newBridge) public onlyOwner {
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 onlyOwner {
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 onlyOwner {
morpherRewards = _newRewardsAddress;
emit RewardsChange(_newRewardsAddress, rewardBasisPoints);
}
function setRewardBasisPoints(uint256 _newRewardBasisPoints) public onlyOwner {
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 onlyOwner {
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;
/**
* @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;
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;
contract Migrations {
address public owner;
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) _;
}
constructor() public {
owner = msg.sender;
}
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
pragma solidity 0.5.16;
import "./SafeMath.sol";
import "./MorpherState.sol";
import "./MorpherTradeEngine.sol";
// ----------------------------------------------------------------------------------
// Administrator of the Morpher platform
// ----------------------------------------------------------------------------------
contract MorpherAdmin {
MorpherState state;
MorpherTradeEngine tradeEngine;
using SafeMath for uint256;
// ----------------------------------------------------------------------------
// Precision of prices and leverage
// ----------------------------------------------------------------------------
modifier onlyAdministrator {
require(msg.sender == state.getAdministrator(), "Function can only be called by the Administrator.");
_;
}
constructor(address _stateAddress, address _tradeEngine) public {
state = MorpherState(_stateAddress);
tradeEngine = MorpherTradeEngine(_tradeEngine);
}
// ----------------------------------------------------------------------------
// Administrative functions
// Set state address and maximum permitted leverage on platform
// ----------------------------------------------------------------------------
function setMorpherState(address _stateAddress) public onlyAdministrator {
state = MorpherState(_stateAddress);
}
function setMorpherTradeEngine(address _tradeEngine) public onlyAdministrator {
tradeEngine = MorpherTradeEngine(_tradeEngine);
}
// ----------------------------------------------------------------------------------
// stockSplits(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _nominator, uint256 _denominator)
// Experimental and untested
// ----------------------------------------------------------------------------------
function stockSplits(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _nominator, uint256 _denominator) public onlyAdministrator {
require(state.getMarketActive(_marketId) == false, "Market must be paused to process stock splits.");
// If no _fromIx and _toIx specified, do entire _list
if (_fromIx == 0) {
_fromIx = 1;
}
if (_toIx == 0) {
_toIx = state.getMaxMappingIndex(_marketId);
}
uint256 _positionLongShares;
uint256 _positionShortShares;
uint256 _positionAveragePrice;
uint256 _positionAverageSpread;
uint256 _positionAverageLeverage;
uint256 _liquidationPrice;
address _address;
for (uint256 i = _fromIx; i <= _toIx; i++) {
// GET position from state
// multiply with nominator, divide by denominator (longShares/shortShares/meanEntry/meanSpread)
// Write back to state
_address = state.getExposureMappingAddress(_marketId, i);
(_positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice) = state.getPosition(_address, _marketId);
_positionLongShares = _positionLongShares.mul(_denominator).div(_nominator);
_positionShortShares = _positionShortShares.mul(_denominator).div(_nominator);
_positionAveragePrice = _positionAveragePrice.mul(_nominator).div(_denominator);
_positionAverageSpread = _positionAverageSpread.mul(_nominator).div(_denominator);
if (_positionShortShares > 0) {
_liquidationPrice = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, false);
} else {
_liquidationPrice = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, true);
}
state.setPosition(_address, _marketId, now, _positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice);
}
}
// ----------------------------------------------------------------------------------
// contractRolls(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _rollUp, uint256 _rollDown)
// Experimental and untested
// ----------------------------------------------------------------------------------
function contractRolls(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _rollUp, uint256 _rollDown) public onlyAdministrator {
// If no _fromIx and _toIx specified, do entire _list
// dividends set meanEntry down, rolls either up or down
require(state.getMarketActive(_marketId) == false, "Market must be paused to process rolls.");
// If no _fromIx and _toIx specified, do entire _list
if (_fromIx == 0) {
_fromIx = 1;
}
if (_toIx == 0) {
_toIx = state.getMaxMappingIndex(_marketId);
}
uint256 _positionLongShares;
uint256 _positionShortShares;
uint256 _positionAveragePrice;
uint256 _positionAverageSpread;
uint256 _positionAverageLeverage;
uint256 _liquidationPrice;
address _address;
for (uint256 i = _fromIx; i <= _toIx; i++) {
// GET position from state
// shift by _upMove and _downMove (one of them is supposed to be zero)
// Write back to state
_address = state.getExposureMappingAddress(_marketId, i);
(_positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice) = state.getPosition(_address, _marketId);
_positionAveragePrice = _positionAveragePrice.add(_rollUp).sub(_rollDown);
if (_positionShortShares > 0) {
_liquidationPrice = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, false);
} else {
_liquidationPrice = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, true);
}
state.setPosition(_address, _marketId, now, _positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice);
}
}
// ----------------------------------------------------------------------------------
// stockDividends()
// May want to add support for dividends later
// ----------------------------------------------------------------------------------
/* function stockDividends(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _meanEntryUp, uint256 _meanEntryDown) public onlyOracle returns (bool _success){
}
*/
}
pragma solidity 0.5.16;
import "./Ownable.sol";
import "./SafeMath.sol";
import "./IERC20.sol";
// ----------------------------------------------------------------------------------
// Holds the Airdrop Token balance on contract address
// AirdropAdmin can authorize addresses to receive airdrop.
// Users have to claim their airdrop actively or Admin initiates transfer.
// ----------------------------------------------------------------------------------
contract MorpherAirdrop is Ownable {
using SafeMath for uint256;
// ----------------------------------------------------------------------------
// Mappings for authorized / claimed airdrop
// ----------------------------------------------------------------------------
mapping(address => uint256) private airdropClaimed;
mapping(address => uint256) private airdropAuthorized;
uint256 public totalAirdropAuthorized;
uint256 public totalAirdropClaimed;
address public airdropAdmin;
address public morpherToken;
// ----------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------
event AirdropSent(address indexed _operator, address indexed _recipient, uint256 _amountClaimed, uint256 _amountAuthorized);
event SetAirdropAuthorized(address indexed _recipient, uint256 _amountClaimed, uint256 _amountAuthorized);
constructor(address _airdropAdminAddress, address _morpherToken, address _coldStorageOwnerAddress) public {
setAirdropAdmin(_airdropAdminAddress);
setMorpherTokenAddress(_morpherToken);
transferOwnership(_coldStorageOwnerAddress);
}
modifier onlyAirdropAdmin {
require(msg.sender == airdropAdmin, "MorpherAirdrop: can only be called by Airdrop Administrator.");
_;
}
// ----------------------------------------------------------------------------
// Administrative functions
// ----------------------------------------------------------------------------
function setAirdropAdmin(address _address) public onlyOwner {
airdropAdmin = _address;
}
function setMorpherTokenAddress(address _address) public onlyOwner {
morpherToken = _address;
}
// ----------------------------------------------------------------------------
// Get airdrop amount authorized for or claimed by address
// ----------------------------------------------------------------------------
function getAirdropClaimed(address _userAddress) public view returns (uint256 _amount) {
return airdropClaimed[_userAddress];
}
function getAirdropAuthorized(address _userAddress) public view returns (uint256 _balance) {
return airdropAuthorized[_userAddress];
}
function getAirdrop(address _userAddress) public view returns(uint256 _claimed, uint256 _authorized) {
return (airdropClaimed[_userAddress], airdropAuthorized[_userAddress]);
}
// ----------------------------------------------------------------------------
// Airdrop Administrator can authorize airdrop amount per address
// ----------------------------------------------------------------------------
function setAirdropAuthorized(address _userAddress, uint256 _authorized) public onlyAirdropAdmin {
// Can only set authorized amount to be higher than claimed
require(_authorized >= airdropClaimed[_userAddress], "MorpherAirdrop: airdrop authorized must be larger than claimed.");
// Authorized amount can be higher or lower than previously authorized amount, adjust accordingly
totalAirdropAuthorized = totalAirdropAuthorized.sub(getAirdropAuthorized(_userAddress)).add(_authorized);
airdropAuthorized[_userAddress] = _authorized;
emit SetAirdropAuthorized(_userAddress, airdropClaimed[_userAddress], _authorized);
}
// ----------------------------------------------------------------------------
// User claims their entire airdrop
// ----------------------------------------------------------------------------
function claimAirdrop() public {
uint256 _amount = airdropAuthorized[msg.sender].sub(airdropClaimed[msg.sender]);
_sendAirdrop(msg.sender, _amount);
}
// ----------------------------------------------------------------------------
// User claims part of their airdrop
// ----------------------------------------------------------------------------
function claimSomeAirdrop(uint256 _amount) public {
_sendAirdrop(msg.sender, _amount);
}
// ----------------------------------------------------------------------------
// Administrator sends user their entire airdrop
// ----------------------------------------------------------------------------
function adminSendAirdrop(address _recipient) public onlyAirdropAdmin {
uint256 _amount = airdropAuthorized[_recipient].sub(airdropClaimed[_recipient]);
_sendAirdrop(_recipient, _amount);
}
// ----------------------------------------------------------------------------
// Administrator sends user part of their airdrop
// ----------------------------------------------------------------------------
function adminSendSomeAirdrop(address _recipient, uint256 _amount) public onlyAirdropAdmin {
_sendAirdrop(_recipient, _amount);
}
// ----------------------------------------------------------------------------
// Administrator sends user entire airdrop
// ----------------------------------------------------------------------------
function _sendAirdrop(address _recipient, uint256 _amount) private {
require(airdropAuthorized[_recipient] >= airdropClaimed[_recipient].add(_amount), "MorpherAirdrop: amount exceeds authorized airdrop amount.");
airdropClaimed[_recipient] = airdropClaimed[_recipient].add(_amount);
totalAirdropClaimed = totalAirdropClaimed.add(_amount);
IERC20(morpherToken).transfer(_recipient, _amount);
emit AirdropSent(msg.sender, _recipient, airdropClaimed[_recipient], airdropAuthorized[_recipient]);
}
// ----------------------------------------------------------------------------
// Administrator sends user part of their airdrop
// ----------------------------------------------------------------------------
function adminAuthorizeAndSend(address _recipient, uint256 _amount) public onlyAirdropAdmin {
setAirdropAuthorized(_recipient, getAirdropAuthorized(_recipient).add(_amount));
_sendAirdrop(_recipient, _amount);
}
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function () external payable {
revert("MorpherAirdrop: you can't deposit Ether here");
}
}
// ------------------------------------------------------------------------
// MorpherBridge
// Handles deposit to and withdraws from the side chain, writing of the merkle
// root to the main chain by the side chain operator, and enforces a rolling 24 hours
// token withdraw limit from side chain to main chain.
// If side chain operator doesn't write a merkle root hash to main chain for more than
// 72 hours positions and balaces from side chain can be transferred to main chain.
// ------------------------------------------------------------------------
pragma solidity 0.5.16;
import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";
import "./MerkleProof.sol";
contract MorpherBridge is Ownable {
MorpherState state;
using SafeMath for uint256;
event TransferToLinkedChain(
address indexed from,
uint256 tokens,
uint256 totalTokenSent,
uint256 timeStamp,
uint256 transferNonce,
bytes32 indexed transferHash
);
event TrustlessWithdrawFromSideChain(address indexed from, uint256 tokens);
event OperatorChainTransfer(address indexed from, uint256 tokens, bytes32 sidechainTransactionHash);
event ClaimFailedTransferToSidechain(address indexed from, uint256 tokens);
event PositionRecoveryFromSideChain(address indexed from, bytes32 positionHash);
event TokenRecoveryFromSideChain(address indexed from, bytes32 positionHash);
event SideChainMerkleRootUpdated(bytes32 _rootHash);
event WithdrawLimitReset();
event WithdrawLimitChanged(uint256 _withdrawLimit);
event LinkState(address _address);
constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
setMorpherState(_stateAddress);
transferOwnership(_coldStorageOwnerAddress);
}
modifier onlySideChainOperator {
require(msg.sender == state.getSideChainOperator(), "MorpherBridge: Function can only be called by Sidechain Operator.");
_;
}
modifier sideChainInactive {
require(now - state.inactivityPeriod() > state.getSideChainMerkleRootWrittenAtTime(), "MorpherBridge: Function can only be called if sidechain is inactive.");
_;
}
modifier fastTransfers {
require(state.fastTransfersEnabled() == true, "MorpherBridge: Fast transfers have been disabled permanently.");
_;
}
modifier onlyMainchain {
require(state.mainChain() == true, "MorpherBridge: Function can only be executed on Ethereum." );
_;
}
// ------------------------------------------------------------------------
// Links Token Contract with State
// ------------------------------------------------------------------------
function setMorpherState(address _stateAddress) public onlyOwner {
state = MorpherState(_stateAddress);
emit LinkState(_stateAddress);
}
function setInactivityPeriod(uint256 _periodInSeconds) private {
state.setInactivityPeriod(_periodInSeconds);
}
function disableFastTransfers() public onlyOwner {
state.disableFastWithdraws();
}
function updateSideChainMerkleRoot(bytes32 _rootHash) public onlySideChainOperator {
state.setSideChainMerkleRoot(_rootHash);
emit SideChainMerkleRootUpdated(_rootHash);
}
function resetLast24HoursAmountWithdrawn() public onlySideChainOperator {
state.resetLast24HoursAmountWithdrawn();
emit WithdrawLimitReset();
}
function set24HourWithdrawLimit(uint256 _withdrawLimit) public onlySideChainOperator {
state.set24HourWithdrawLimit(_withdrawLimit);
emit WithdrawLimitChanged(_withdrawLimit);
}
function getTokenSentToLinkedChain(address _address) public view returns (uint256 _token) {
return state.getTokenSentToLinkedChain(_address);
}
function getTokenClaimedOnThisChain(address _address) public view returns (uint256 _token) {
return state.getTokenClaimedOnThisChain(_address);
}
function getTokenSentToLinkedChainTime(address _address) public view returns (uint256 _time) {
return state.getTokenSentToLinkedChainTime(_address);
}
// ------------------------------------------------------------------------
// verifyWithdrawOk(uint256 _amount)
// Checks if creating _amount token on main chain does not violate the 24 hour transfer limit
// ------------------------------------------------------------------------
function verifyWithdrawOk(uint256 _amount) public returns (bool _authorized) {
uint256 _lastWithdrawLimitReductionTime = state.lastWithdrawLimitReductionTime();
uint256 _withdrawLimit24Hours = state.withdrawLimit24Hours();
if (now > _lastWithdrawLimitReductionTime) {
uint256 _timePassed = now.sub(_lastWithdrawLimitReductionTime);
state.update24HoursWithdrawLimit(_timePassed.mul(_withdrawLimit24Hours).div(1 days));
}
if (state.last24HoursAmountWithdrawn().add(_amount) <= _withdrawLimit24Hours) {
return true;
} else {
return false;
}
}
// ------------------------------------------------------------------------
// transferToSideChain(uint256 _tokens)
// Transfer token to Morpher's side chain to trade without fees and near instant
// settlement.
// - Owner's account must have sufficient balance to transfer
// - 0 value transfers are not supported
// Token are burned on the main chain and are created and credited to msg.sender
// on the side chain
// ------------------------------------------------------------------------
function transferToSideChain(uint256 _tokens) public {
require(_tokens >= 0, "MorpherBridge: Amount of tokens must be positive.");
require(state.balanceOf(msg.sender) >= _tokens, "MorpherBridge: Insufficient balance.");
state.burn(msg.sender, _tokens);
uint256 _newTokenSentToLinkedChain = getTokenSentToLinkedChain(msg.sender).add(_tokens);
uint256 _transferNonce = state.getBridgeNonce();
uint256 _timeStamp = now;
bytes32 _transferHash = keccak256(
abi.encodePacked(
msg.sender,
_tokens,
_newTokenSentToLinkedChain,
_timeStamp,
_transferNonce
)
);
state.setTokenSentToLinkedChain(msg.sender, _newTokenSentToLinkedChain);
emit TransferToLinkedChain(msg.sender, _tokens, _newTokenSentToLinkedChain, _timeStamp, _transferNonce, _transferHash);
}
// ------------------------------------------------------------------------
// fastTransferFromSideChain(uint256 _numOfToken, uint256 _tokenBurnedOnLinkedChain, bytes32[] memory _proof)
// The sidechain operator can credit users with token they burend on the sidechain. Transfers
// happen immediately. To be removed after Beta.
// ------------------------------------------------------------------------
function fastTransferFromSideChain(address _address, uint256 _numOfToken, uint256 _tokenBurnedOnLinkedChain, bytes32 _sidechainTransactionHash) public onlySideChainOperator fastTransfers {
uint256 _tokenClaimed = state.getTokenClaimedOnThisChain(_address);
require(verifyWithdrawOk(_numOfToken), "MorpherBridge: Withdraw amount exceeds permitted 24 hour limit. Please try again in a few hours.");
require(_tokenClaimed.add(_numOfToken) <= _tokenBurnedOnLinkedChain, "MorpherBridge: Token amount exceeds token deleted on linked chain.");
_chainTransfer(_address, _tokenClaimed, _numOfToken);
emit OperatorChainTransfer(_address, _numOfToken, _sidechainTransactionHash);
}
// ------------------------------------------------------------------------
// trustlessTransferFromSideChain(uint256 _numOfToken, uint256 _claimLimit, bytes32[] memory _proof)
// Performs a merkle proof on the number of token that have been burned by the user on the side chain.
// If the number of token claimed on the main chain is less than the number of burned token on the side chain
// the difference (or less) can be claimed on the main chain.
// ------------------------------------------------------------------------
function trustlessTransferFromLinkedChain(uint256 _numOfToken, uint256 _claimLimit, bytes32[] memory _proof) public {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _claimLimit));
uint256 _tokenClaimed = state.getTokenClaimedOnThisChain(msg.sender);
require(mProof(_proof, leaf), "MorpherBridge: Merkle Proof failed. Please make sure you entered the correct claim limit.");
require(verifyWithdrawOk(_numOfToken), "MorpherBridge: Withdraw amount exceeds permitted 24 hour limit. Please try again in a few hours.");
require(_tokenClaimed.add(_numOfToken) <= _claimLimit, "MorpherBridge: Token amount exceeds token deleted on linked chain.");
_chainTransfer(msg.sender, _tokenClaimed, _numOfToken);
emit TrustlessWithdrawFromSideChain(msg.sender, _numOfToken);
}
// ------------------------------------------------------------------------
// _chainTransfer(address _address, uint256 _tokenClaimed, uint256 _numOfToken)
// Creates token on the chain for the user after proving their distruction on the
// linked chain has been proven before
// ------------------------------------------------------------------------
function _chainTransfer(address _address, uint256 _tokenClaimed, uint256 _numOfToken) private {
state.setTokenClaimedOnThisChain(_address, _tokenClaimed.add(_numOfToken));
state.add24HoursWithdrawn(_numOfToken);
state.mint(_address, _numOfToken);
}
// ------------------------------------------------------------------------
// claimFailedTransferToSidechain(uint256 _wrongSideChainBalance, bytes32[] memory _proof)
// If token sent to side chain were not credited to the user on the side chain within inactivityPeriod
// they can reclaim the token on the main chain by submitting the proof that their
// side chain balance is less than the number of token sent from main chain.
// ------------------------------------------------------------------------
function claimFailedTransferToSidechain(uint256 _wrongSideChainBalance, bytes32[] memory _proof) public {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _wrongSideChainBalance));
uint256 _tokenSentToLinkedChain = getTokenSentToLinkedChain(msg.sender);
uint256 _tokenSentToLinkedChainTime = getTokenSentToLinkedChainTime(msg.sender);
uint256 _inactivityPeriod = state.inactivityPeriod();
require(now > _tokenSentToLinkedChainTime.add(_inactivityPeriod), "MorpherBridge: Failed deposits can only be claimed after inactivity period.");
require(_wrongSideChainBalance < _tokenSentToLinkedChain, "MorpherBridge: Other chain credit is greater equal to wrongSideChainBalance.");
require(verifyWithdrawOk(_tokenSentToLinkedChain.sub(_wrongSideChainBalance)), "MorpherBridge: Claim amount exceeds permitted 24 hour limit.");
require(mProof(_proof, leaf), "MorpherBridge: Merkle Proof failed. Enter total amount of deposits on side chain.");
uint256 _claimAmount = _tokenSentToLinkedChain.sub(_wrongSideChainBalance);
state.setTokenSentToLinkedChain(msg.sender, _tokenSentToLinkedChain.sub(_claimAmount));
state.add24HoursWithdrawn(_claimAmount);
state.mint(msg.sender, _claimAmount);
emit ClaimFailedTransferToSidechain(msg.sender, _claimAmount);
}
// ------------------------------------------------------------------------
// recoverPositionFromSideChain(bytes32[] memory _proof, bytes32 _leaf, bytes32 _marketId, uint256 _timeStamp, uint256 _longShares, uint256 _shortShares, uint256 _meanEntryPrice, uint256 _meanEntrySpread, uint256 _meanEntryLeverage)
// Failsafe against side chain operator becoming inactive or withholding Times (Time withhold attack).
// After 72 hours of no update of the side chain merkle root users can withdraw their last recorded
// positions from side chain to main chain. Overwrites eventually existing position on main chain.
// ------------------------------------------------------------------------
function recoverPositionFromSideChain(
bytes32[] memory _proof,
bytes32 _leaf,
bytes32 _marketId,
uint256 _timeStamp,
uint256 _longShares,
uint256 _shortShares,
uint256 _meanEntryPrice,
uint256 _meanEntrySpread,
uint256 _meanEntryLeverage,
uint256 _liquidationPrice
) public sideChainInactive onlyMainchain {
require(_leaf == state.getPositionHash(msg.sender, _marketId, _timeStamp, _longShares, _shortShares, _meanEntryPrice, _meanEntrySpread, _meanEntryLeverage, _liquidationPrice), "MorpherBridge: leaf does not equal position hash.");
require(state.getPositionClaimedOnMainChain(_leaf) == false, "MorpherBridge: Position already transferred.");
require(mProof(_proof,_leaf) == true, "MorpherBridge: Merkle proof failed.");
state.setPositionClaimedOnMainChain(_leaf);
state.setPosition(msg.sender, _marketId, _timeStamp, _longShares, _shortShares, _meanEntryPrice, _meanEntrySpread, _meanEntryLeverage, _liquidationPrice);
emit PositionRecoveryFromSideChain(msg.sender, _leaf);
// Remark: After resuming operations side chain operator has 72 hours to sync and eliminate transferred positions on side chain to avoid double spend
}
// ------------------------------------------------------------------------
// recoverTokenFromSideChain(bytes32[] memory _proof, bytes32 _leaf, bytes32 _marketId, uint256 _timeStamp, uint256 _longShares, uint256 _shortShares, uint256 _meanEntryPrice, uint256 _meanEntrySpread, uint256 _meanEntryLeverage)
// Failsafe against side chain operator becoming inactive or withholding times (time withhold attack).
// After 72 hours of no update of the side chain merkle root users can withdraw their last recorded
// token balance from side chain to main chain.
// ------------------------------------------------------------------------
function recoverTokenFromSideChain(bytes32[] memory _proof, bytes32 _leaf, uint256 _balance) public sideChainInactive onlyMainchain {
// Require side chain root hash not set on Mainchain for more than 72 hours (=3 days)
require(_leaf == state.getBalanceHash(msg.sender, _balance), "MorpherBridge: Wrong balance.");
require(state.getPositionClaimedOnMainChain(_leaf) == false, "MorpherBridge: Token already transferred.");
require(mProof(_proof,_leaf) == true, "MorpherBridge: Merkle proof failed.");
require(verifyWithdrawOk(_balance), "MorpherBridge: Withdraw amount exceeds permitted 24 hour limit.");
state.setPositionClaimedOnMainChain(_leaf);
_chainTransfer(msg.sender, state.getTokenClaimedOnThisChain(msg.sender), _balance);
emit TokenRecoveryFromSideChain(msg.sender, _leaf);
// Remark: Side chain operator must adjust side chain balances for token recoveries before restarting operations to avoid double spend
}
// ------------------------------------------------------------------------
// mProof(bytes32[] memory _proof, bytes32 _leaf)
// Computes merkle proof against the root hash of the sidechain stored in Morpher state
// ------------------------------------------------------------------------
function mProof(bytes32[] memory _proof, bytes32 _leaf) public view returns(bool _isTrue) {
return MerkleProof.verify(_proof, state.getSideChainMerkleRoot(), _leaf);
}
}
pragma solidity 0.5.16;
import "./Ownable.sol";
import "./SafeMath.sol";
import "./IERC20.sol";
// ----------------------------------------------------------------------------------
// Escrow contract to safely store and release the token allocated to Morpher at
// protocol inception
// ----------------------------------------------------------------------------------
contract MorpherEscrow is Ownable{
using SafeMath for uint256;
uint256 public lastEscrowTransferTime;
address public recipient;
address public morpherToken;
uint256 public constant RELEASEAMOUNT = 10**25;
uint256 public constant RELEASEPERIOD = 30 days;
event EscrowReleased(uint256 _released, uint256 _leftInEscrow);
constructor(address _recipientAddress, address _morpherToken, address _coldStorageOwnerAddress) public {
setRecipientAddress(_recipientAddress);
setMorpherTokenAddress(_morpherToken);
lastEscrowTransferTime = now;
transferOwnership(_coldStorageOwnerAddress);
}
// ----------------------------------------------------------------------------------
// Owner can modify recipient address and update morpherToken adddress
// ----------------------------------------------------------------------------------
function setRecipientAddress(address _recipientAddress) public onlyOwner {
recipient = _recipientAddress;
}
function setMorpherTokenAddress(address _address) public onlyOwner {
morpherToken = _address;
}
// ----------------------------------------------------------------------------------
// Anyone can release funds from escrow if enough time has elapsed
// Every 30 days 1% of the total initial supply or 10m token are released to Morpher
// ----------------------------------------------------------------------------------
function releaseFromEscrow() public {
require(IERC20(morpherToken).balanceOf(address(this)) > 0, "No funds left in escrow.");
uint256 _releasedAmount;
if (now > lastEscrowTransferTime.add(RELEASEPERIOD)) {
if (IERC20(morpherToken).balanceOf(address(this)) > RELEASEAMOUNT) {
_releasedAmount = RELEASEAMOUNT;
} else {
_releasedAmount = IERC20(morpherToken).balanceOf(address(this));
}
IERC20(morpherToken).transfer(recipient, _releasedAmount);
lastEscrowTransferTime = lastEscrowTransferTime.add(RELEASEPERIOD);
emit EscrowReleased(_releasedAmount, IERC20(morpherToken).balanceOf(address(this)));
}
}
}
pragma solidity 0.5.16;
// ------------------------------------------------------------------------
// Morpher Governance (MAIN CHAIN ONLY)
//
// Every user able and willig to lock up sufficient token can become a validator
// of the Morpher protocol. Validators function similiar to a board of directors
// and vote on the protocol Administrator and the Oracle contract.
// The Administrator (=Protocol CEO) has the power to add/delete markets and to
// pause the contracts to allow for updates.
// The Oracle contract is the address of the contract allowed to fetch prices
// from outside the smart contract.
//
// It becomes progressively harder to become a valdiator. Each new validator
// has to lock up (numberOfValidators + 1) * 10m Morpher token. Upon stepping
// down as validator only 99% of the locked up token are returned, the other 1%
// are burned.
//
// Governance is expected to become more sophisticated in the future
// ------------------------------------------------------------------------
import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";
contract MorpherGovernance is Ownable {
using SafeMath for uint256;
MorpherState state;
event BecomeValidator(address indexed _sender, uint256 indexed _myValidatorIndex);
event StepDownAsValidator(address indexed _sender, uint256 indexed _myValidatorIndex);
event ElectedAdministrator(address indexed _administratorAddress, uint256 _votes);
event ElectedOracle(address indexed _oracleAddress, uint256 _votes);
uint256 public constant MINVALIDATORLOCKUP = 10**25;
uint256 public constant MAXVALIDATORS = 21;
uint256 public constant VALIDATORWARMUPPERIOD = 7 days;
uint256 public numberOfValidators;
uint256 public lastValidatorJoined;
uint256 public rewardBasisPoints;
address public morpherToken;
mapping(address => uint256) private validatorIndex;
mapping(address => uint256) private validatorJoinedAtTime;
mapping(uint256 => address) private validatorAddress;
mapping(address => address) private oracleVote;
mapping(address => address) private administratorVote;
mapping(address => uint256) private countVotes;
constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
setMorpherState(_stateAddress);
transferOwnership(_coldStorageOwnerAddress);
}
modifier onlyValidator() {
require(isValidator(msg.sender), "MorpherGovernance: Only Validators can invoke that function.");
_;
}
function setMorpherState(address _stateAddress) private {
state = MorpherState(_stateAddress);
}
function setMorpherTokenAddress(address _address) public onlyOwner {
morpherToken = _address;
}
function getValidatorAddress(uint256 _index) public view returns (address _address) {
return validatorAddress[_index];
}
function getValidatorIndex(address _address) public view returns (uint256 _index) {
return validatorIndex[_address];
}
function isValidator(address _address) public view returns (bool) {
return validatorIndex[_address] > 0;
}
function setOracle(address _oracleAddress) private {
state.setOracleContract(_oracleAddress);
}
function setAdministrator(address _administratorAddress) private {
state.setAdministrator(_administratorAddress);
}
function getMorpherAdministrator() public view returns (address _address) {
return state.getAdministrator();
}
function getMorpherOracle() public view returns (address _address) {
return state.getOracleContract();
}
function getOracleVote(address _address) public view returns (address _votedOracleAddress) {
return oracleVote[_address];
}
function becomeValidator() public {
// To become a validator you have to lock up 10m * (number of validators + 1) Morpher Token in escrow
// After a warmup period of 7 days the new validator can vote on Oracle contract and protocol Administrator
uint256 _requiredAmount = MINVALIDATORLOCKUP.mul(numberOfValidators.add(1));
require(state.balanceOf(msg.sender) >= _requiredAmount, "MorpherGovernance: Insufficient balance to become Validator.");
require(isValidator(msg.sender) == false, "MorpherGovernance: Address is already Validator.");
require(numberOfValidators <= MAXVALIDATORS, "MorpherGovernance: number of Validators can not exceed Max Validators.");
state.transfer(msg.sender, address(this), _requiredAmount);
numberOfValidators = numberOfValidators.add(1);
validatorIndex[msg.sender] = numberOfValidators;
validatorJoinedAtTime[msg.sender] = now;
lastValidatorJoined = now;
validatorAddress[numberOfValidators] = msg.sender;
emit BecomeValidator(msg.sender, numberOfValidators);
}
function stepDownValidator() public onlyValidator {
// Stepping down as validator nullifies the validator's votes and releases his token
// from escrow. If the validator stepping down is not the validator that joined last,
// all validators who joined after the validator stepping down receive 10^7 * 0.99 token from
// escrow, and their validator ordinal number is reduced by one. E.g. if validator 3 of 5 steps down
// validator 4 becomes validator 3, and validator 5 becomes validator 4. Both receive 10^7 * 0.99 token
// from escrow, as their new position requires fewer token in lockup. 1% of the token released from escrow
// are burned for every validator receiving a payout.
// Burning prevents vote delay attacks: validators stepping down and re-joining could
// delay votes for VALIDATORWARMUPPERIOD.
uint256 _myValidatorIndex = validatorIndex[msg.sender];
require(state.balanceOf(address(this)) >= MINVALIDATORLOCKUP.mul(numberOfValidators), "MorpherGovernance: Escrow does not have enough funds. Should not happen.");
// Stepping down as validator potentially releases token to the other validatorAddresses
for (uint256 i = _myValidatorIndex; i < numberOfValidators; i++) {
validatorAddress[i] = validatorAddress[i+1];
validatorIndex[validatorAddress[i]] = i;
// Release 9.9m of token to every validator moving up, burn 0.1m token
state.transfer(address(this), validatorAddress[i], MINVALIDATORLOCKUP.div(100).mul(99));
state.burn(address(this), MINVALIDATORLOCKUP.div(100));
}
// Release 99% of escrow token of validator dropping out, burn 1%
validatorAddress[numberOfValidators] = address(0);
validatorIndex[msg.sender] = 0;
validatorJoinedAtTime[msg.sender] = 0;
oracleVote[msg.sender] = address(0);
administratorVote[msg.sender] = address(0);
numberOfValidators = numberOfValidators.sub(1);
countOracleVote();
countAdministratorVote();
state.transfer(address(this), msg.sender, MINVALIDATORLOCKUP.mul(_myValidatorIndex).div(100).mul(99));
state.burn(address(this), MINVALIDATORLOCKUP.mul(_myValidatorIndex).div(100));
emit StepDownAsValidator(msg.sender, validatorIndex[msg.sender]);
}
function voteOracle(address _oracleAddress) public onlyValidator {
require(validatorJoinedAtTime[msg.sender].add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: Validator was just appointed and is not eligible to vote yet.");
require(lastValidatorJoined.add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: New validator joined the board recently, please wait for the end of the warm up period.");
oracleVote[msg.sender] = _oracleAddress;
// Count Oracle Votes
(address _votedOracleAddress, uint256 _votes) = countOracleVote();
emit ElectedOracle(_votedOracleAddress, _votes);
}
function voteAdministrator(address _administratorAddress) public onlyValidator {
require(validatorJoinedAtTime[msg.sender].add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: Validator was just appointed and is not eligible to vote yet.");
require(lastValidatorJoined.add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: New validator joined the board recently, please wait for the end of the warm up period.");
administratorVote[msg.sender] = _administratorAddress;
// Count Administrator Votes
(address _appointedAdministrator, uint256 _votes) = countAdministratorVote();
emit ElectedAdministrator(_appointedAdministrator, _votes);
}
function countOracleVote() public returns (address _votedOracleAddress, uint256 _votes) {
// Count oracle votes
for (uint256 i = 1; i <= numberOfValidators; i++) {
countVotes[oracleVote[validatorAddress[i]]]++;
if (countVotes[oracleVote[validatorAddress[i]]] > _votes) {
_votes = countVotes[oracleVote[validatorAddress[i]]];
_votedOracleAddress = oracleVote[validatorAddress[i]];
}
}
// Evaluate: Simple majority of Validators resets oracleAddress
if (_votes > numberOfValidators.div(2)) {
setOracle(_votedOracleAddress);
}
for (uint256 i = 1; i <= numberOfValidators; i++) {
countVotes[administratorVote[validatorAddress[i]]] = 0;
}
return(_votedOracleAddress, _votes);
}
function countAdministratorVote() public returns (address _appointedAdministrator, uint256 _votes) {
// Count Administrator votes
for (uint256 i=1; i<=numberOfValidators; i++) {
countVotes[administratorVote[validatorAddress[i]]]++;
if (countVotes[administratorVote[validatorAddress[i]]] > _votes) {
_votes = countVotes[administratorVote[validatorAddress[i]]];
_appointedAdministrator = administratorVote[validatorAddress[i]];
}
}
// Evaluate: Simple majority of Validators resets administratorAddress
if (_votes > numberOfValidators / 2) {
setAdministrator(_appointedAdministrator);
}
for (uint256 i = 1; i <= numberOfValidators; i++) {
countVotes[administratorVote[validatorAddress[i]]] = 0;
}
return(_appointedAdministrator, _votes);
}
}
pragma solidity 0.5.16;
import "./Ownable.sol";
import "./MorpherTradeEngine.sol";
// ----------------------------------------------------------------------------------
// Morpher Oracle contract
// 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;
bool public paused;
uint256 public gasForCallback;
address payable public callBackCollectionAddress;
mapping(address => bool) public callBackAddress;
// ----------------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------------
event OrderCreated(
bytes32 indexed _orderId,
address indexed _address,
bytes32 indexed _marketId,
bool _tradeAmountGivenInShares,
uint256 _tradeAmount,
bool _tradeDirection,
uint256 _orderLeverage
);
event LiquidationOrderCreated(
bytes32 indexed _orderId,
address _sender,
address indexed _address,
bytes32 indexed _marketId
);
event OrderProcessed(
bytes32 indexed _orderId,
uint256 _price,
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,
bool _tradeAmountGivenInShares,
uint256 _tradeAmount,
bool _tradeDirection,
uint256 _orderLeverage
);
event OrderCancelled(
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
);
modifier onlyOracleOperator {
require(isCallbackAddress(msg.sender), "MorpherOracle: Only the oracle operator can call this function.");
_;
}
modifier notPaused {
require(paused == false, "MorpherOracle: Oracle paused, aborting");
_;
}
constructor(address _tradeEngineAddress, address _callBackAddress, address payable _gasCollectionAddress, uint256 _gasForCallback, address _coldStorageOwnerAddress) public {
setTradeEngineAddress(_tradeEngineAddress);
enableCallbackAddress(_callBackAddress);
setCallbackCollectionAddress(_gasCollectionAddress);
setGasForCallback(_gasForCallback);
transferOwnership(_coldStorageOwnerAddress);
}
// ----------------------------------------------------------------------------------
// 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 setGasForCallback(uint256 _gasForCallback) public onlyOwner {
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);
}
// ----------------------------------------------------------------------------------
// emitOrderFailed
// Can be called by Oracle Operator to notifiy user of failed order
// ----------------------------------------------------------------------------------
function emitOrderFailed(
bytes32 _orderId,
address _address,
bytes32 _marketId,
bool _tradeAmountGivenInShares,
uint256 _tradeAmount,
bool _tradeDirection,
uint256 _orderLeverage
) public onlyOracleOperator {
emit OrderFailed(
_orderId,
_address,
_marketId,
_tradeAmountGivenInShares,
_tradeAmount,
_tradeDirection,
_orderLeverage);
}
// ----------------------------------------------------------------------------------
// 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,
bool _tradeAmountGivenInShares,
uint256 _tradeAmount,
bool _tradeDirection,
uint256 _orderLeverage
) public payable notPaused 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(msg.sender, _marketId, _tradeAmountGivenInShares, _tradeAmount, _tradeDirection, _orderLeverage);
emit OrderCreated(
_orderId,
msg.sender,
_marketId,
_tradeAmountGivenInShares,
_tradeAmount,
_tradeDirection,
_orderLeverage
);
return _orderId;
}
// ----------------------------------------------------------------------------------
// cancelOrder(bytes32 _orderId)
// Users can cancel their own orders before the _callback has been executed
// ----------------------------------------------------------------------------------
function cancelOrder(bytes32 _orderId) public {
tradeEngine.cancelOrder(_orderId, msg.sender);
emit OrderCancelled(
_orderId,
msg.sender
);
}
// ----------------------------------------------------------------------------------
// Setter/getter functions for pausing 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 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, true, 0, true, 10**8);
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 _spread,
uint256 _liquidationTimestamp,
uint256 _timeStamp
) public onlyOracleOperator notPaused returns (uint256 _newLongShares, uint256 _newShortShares, uint256 _newMeanEntry, uint256 _newMeanSpread, uint256 _newMeanLeverage, uint256 _liquidationPrice) {
(
_newLongShares,
_newShortShares,
_newMeanEntry,
_newMeanSpread,
_newMeanLeverage,
_liquidationPrice
) = tradeEngine.processOrder(_orderId, _price, _spread, _liquidationTimestamp, _timeStamp);
emit OrderProcessed(
_orderId,
_price,
_spread,
_liquidationTimestamp,
_timeStamp,
_newLongShares,
_newShortShares,
_newMeanEntry,
_newMeanSpread,
_newMeanLeverage,
_liquidationPrice
);
return (_newLongShares, _newShortShares, _newMeanEntry, _newMeanSpread, _newMeanLeverage, _liquidationPrice);
}
// ----------------------------------------------------------------------------------
// 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 "./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.mainChain() == true || 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 "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.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;
using SafeMath for uint256;
// ----------------------------------------------------------------------------
// Precision of prices and leverage
// ----------------------------------------------------------------------------
uint256 constant PRECISION = 10**8;
uint256 public orderNonce;
bytes32 public lastOrderId;
// ----------------------------------------------------------------------------
// 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;
bool tradeAmountGivenInShares;
bytes32 marketId;
uint256 tradeAmount;
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;
}
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,
bool _tradeAmountGivenInShares,
uint256 _tradeAmount,
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);
constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
setMorpherState(_stateAddress);
transferOwnership(_coldStorageOwnerAddress);
}
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 getAdministrator() public view returns(address _administrator) {
return state.getAdministrator();
}
// ----------------------------------------------------------------------------
// requestOrderId(address _address, bytes32 _marketId, bool _tradeAmountGivenInShares, uint256 _tradeAmount, 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,
bool _tradeAmountGivenInShares,
uint256 _tradeAmount,
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.");
require(state.getMarketActive(_marketId) == true, "MorpherTradeEngine: market unknown or currently not enabled for trading.");
require(state.getNumberOfRequests(_address) <= state.getNumberOfRequestsLimit() ||
state.getLastRequestBlock(_address) < block.number,
"MorpherTradeEngine: request exceeded maximum permitted requests per block."
);
state.setLastRequestBlock(_address);
state.increaseNumberOfRequests(_address);
orderNonce++;
_orderId = keccak256(
abi.encodePacked(
_address,
block.number,
_marketId,
_tradeAmountGivenInShares,
_tradeAmount,
_tradeDirection,
_orderLeverage,
orderNonce
)
);
lastOrderId = _orderId;
orders[_orderId].userId = _address;
orders[_orderId].marketId = _marketId;
orders[_orderId].tradeAmountGivenInShares = _tradeAmountGivenInShares;
orders[_orderId].tradeAmount = _tradeAmount;
orders[_orderId].tradeDirection = _tradeDirection;
orders[_orderId].orderLeverage = _orderLeverage;
emit OrderIdRequested(
_orderId,
_address,
_marketId,
_tradeAmountGivenInShares,
_tradeAmount,
_tradeDirection,
_orderLeverage
);
return _orderId;
}
// ----------------------------------------------------------------------------
// Getter functions for orders, shares, and positions
// ----------------------------------------------------------------------------
function getOrder(bytes32 _orderId) public view returns (
address _userId,
bytes32 _marketId,
uint256 _tradeAmount,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _orderLeverage
) {
return(
orders[_orderId].userId,
orders[_orderId].marketId,
orders[_orderId].tradeAmount,
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
orders[_orderId].orderLeverage
);
}
function getOrderShares(bytes32 _orderId) public view returns (
uint256 _longSharesOrder,
uint256 _shortSharesOrder,
uint256 _tradeAmount,
bool _tradeDirection,
uint256 _balanceUp,
uint256 _balanceDown) {
return(
orders[_orderId].longSharesOrder,
orders[_orderId].shortSharesOrder,
orders[_orderId].tradeAmount,
orders[_orderId].tradeDirection,
orders[_orderId].balanceUp,
orders[_orderId].balanceDown
);
}
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)
);
}
// ----------------------------------------------------------------------------
// 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 _timeStamp
) 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.");
address _address = orders[_orderId].userId;
bytes32 _marketId = orders[_orderId].marketId;
require(state.getMarketActive(_marketId) == true, "MorpherTradeEngine: market unknown or currently not enabled for trading.");
orders[_orderId].marketPrice = _marketPrice;
orders[_orderId].marketSpread = _marketSpread;
orders[_orderId].timeStamp = _timeStamp;
orders[_orderId].liquidationTimestamp = _liquidationTimestamp;
// Check if previous position on that market was liquidated
if (_liquidationTimestamp > state.getLastUpdated(_address, _marketId)) {
liquidate(_orderId);
}
if (orders[_orderId].tradeAmount > 0) {
if (orders[_orderId].tradeDirection) {
processBuyOrder(_orderId);
} else {
processSellOrder(_orderId);
}
}
delete orders[_orderId];
emit OrderProcessed(
_orderId,
_marketPrice,
_marketSpread,
_liquidationTimestamp,
_timeStamp,
_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.");
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 _liquidationPrice,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _orderLeverage,
bool _sell
) public pure 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 (
_liquidationPrice <= _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));
} 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 _liquidationPrice,
uint256 _marketPrice,
uint256 _marketSpread,
uint256 _orderLeverage,
bool _sell
) public pure 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 <= _liquidationPrice
) {
// 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));
} else {
// We buy a new long position and have to pay the spread
_shareValue = _shareValue.add(_marketSpread.mul(_orderLeverage).div(PRECISION));
}
}
return _shareValue;
}
// ----------------------------------------------------------------------------
// 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].tradeAmountGivenInShares == false) {
// Investment was specified in units of MPH
if (orders[_orderId].tradeAmount <= state.getShortShares(
orders[_orderId].userId,
orders[_orderId].marketId
).mul(
shortShareValue(
state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
PRECISION,
true
))
) {
// Partial closing of short position
orders[_orderId].longSharesOrder = 0;
orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount.div(shortShareValue(
state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
PRECISION,
true
));
} else {
// Closing of entire short position
orders[_orderId].shortSharesOrder = state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId);
orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount.sub((
state.getShortShares(
orders[_orderId].userId,
orders[_orderId].marketId
).mul(
shortShareValue(
state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
PRECISION,
true
))
));
orders[_orderId].longSharesOrder = orders[_orderId].longSharesOrder.div(
longShareValue(
orders[_orderId].marketPrice,
orders[_orderId].orderLeverage,
0,
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
orders[_orderId].orderLeverage,
false
));
}
} else {
// Investment was specified in shares
if (orders[_orderId].tradeAmount <= state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId)) {
// Partial closing of short position
orders[_orderId].longSharesOrder = 0;
orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount;
} else {
// Closing of entire short position
orders[_orderId].shortSharesOrder = state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId);
orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount.sub(
state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId)
);
}
}
// 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].tradeAmountGivenInShares == false) {
// Investment was specified in units of MPH
if (orders[_orderId].tradeAmount <= state.getLongShares(
orders[_orderId].userId,
orders[_orderId].marketId
).mul(
longShareValue(
state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
PRECISION,
true
))) {
// Partial closing of long position
orders[_orderId].shortSharesOrder = 0;
orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount.div(
longShareValue(
state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
PRECISION,
true
));
} else {
// Closing of entire long position
orders[_orderId].longSharesOrder = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount.sub((
state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId
).mul(
longShareValue(
state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
state.getMeanEntryLeverage(orders[_orderId].userId,
orders[_orderId].marketId),
state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
PRECISION,
true
))
));
orders[_orderId].shortSharesOrder = orders[_orderId].shortSharesOrder.div(
shortShareValue(
orders[_orderId].marketPrice,
orders[_orderId].orderLeverage,
orders[_orderId].marketPrice.mul(100),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
orders[_orderId].orderLeverage,
false
));
}
} else {
// Investment was specified in shares
if (orders[_orderId].tradeAmount <= state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId)) {
// Partial closing of long position
orders[_orderId].shortSharesOrder = 0;
orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount;
} else {
// Closing of entire long position
orders[_orderId].longSharesOrder = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount.sub(
state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId)
);
}
}
// 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 = orders[_orderId].longSharesOrder.mul(longShareValue(
state.getMeanEntryPrice(_userId, _marketId),
state.getMeanEntryLeverage(_userId, _marketId),
state.getLiquidationPrice(_userId, _marketId),
orders[_orderId].marketPrice, orders[_orderId].marketSpread,
state.getMeanEntryLeverage(_userId, _marketId),
true
));
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);
}
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);
}
// ----------------------------------------------------------------------------
// closeShort(bytes32 _orderId)
// Closes an existing short position. Average entry price/spread/leverage do not change.
// ----------------------------------------------------------------------------
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 = orders[_orderId].shortSharesOrder.mul(
shortShareValue(
state.getMeanEntryPrice(_userId, _marketId),
state.getMeanEntryLeverage(_userId, _marketId),
state.getLiquidationPrice(_userId, _marketId),
orders[_orderId].marketPrice,
orders[_orderId].marketSpread,
state.getMeanEntryLeverage(_userId, _marketId),
true
));
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);
}
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);
}
if (orders[_orderId].newShortShares > 0) {
orders[_orderId].newLiquidationPrice = getLiquidationPrice(orders[_orderId].newMeanEntryPrice, orders[_orderId].newMeanEntryLeverage, false);
}
return orders[_orderId].newLiquidationPrice;
}
function getLiquidationPrice(uint256 _newMeanEntryPrice, uint256 _newMeanEntryLeverage, bool _long) public pure returns (uint256 _liquidiationPrice) {
if (_long == true) {
_liquidiationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.sub(PRECISION)).div(_newMeanEntryLeverage);
} else {
_liquidiationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.add(PRECISION)).div(_newMeanEntryLeverage);
}
return _liquidiationPrice;
}
// ----------------------------------------------------------------------------
// 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) {
state.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;
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":"bool","name":"_mainChain","type":"bool"},{"internalType":"address","name":"_sideChainOperator","type":"address"},{"internalType":"address","name":"_morpherTreasury","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"administratorAddress","type":"address"}],"name":"AdministratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_bridgeAddress","type":"address"}],"name":"BridgeChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalToken","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[],"name":"FastWithdrawsDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"governanceAddress","type":"address"}],"name":"GovernanceChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_periodLength","type":"uint256"}],"name":"InactivityPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Last24HoursAmountWithdrawnReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rewardsTime","type":"uint256"}],"name":"LastRewardTime","type":"event"},{"anonymous":false,"inputs":[],"name":"LastWithdrawAt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"mainChainWithdrawLimit24","type":"uint256"}],"name":"MainChainWithdrawLimitUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"activateMarket","type":"bytes32"}],"name":"MarketActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"deActivateMarket","type":"bytes32"}],"name":"MarketDeActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxLeverage","type":"uint256"}],"name":"MaximumLeverageChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalToken","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_transferNonce","type":"uint256"}],"name":"NewBridgeNonce","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sideChainOperator","type":"address"}],"name":"NewSideChainOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTotalOnOtherChain","type":"uint256"}],"name":"NewTotalInPositions","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTotalOnOtherChain","type":"uint256"}],"name":"NewTotalOnOtherChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTotalSupply","type":"uint256"}],"name":"NewTotalSupply","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_numberOfRequests","type":"uint256"}],"name":"NumberOfRequestsLimitUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"OperatingRewardMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oracleContract","type":"address"}],"name":"OracleChange","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":"rewardsAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"rewardsBasisPoints","type":"uint256"}],"name":"RewardsChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_last24HoursAmountWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lastWithdrawLimitReductionTime","type":"uint256"}],"name":"RollingWithdrawnAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"SetAllowance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"balanceHash","type":"bytes32"}],"name":"SetBalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"bytes32","name":"marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"longShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shortShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"meanEntryPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"meanEntrySpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"meanEntryLeverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationPrice","type":"uint256"}],"name":"SetPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"sideChainMerkleRoot","type":"bytes32"}],"name":"SideChainMerkleRootUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"blackList","type":"address"},{"indexed":true,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"StateAccessDenied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"whiteList","type":"address"},{"indexed":true,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"StateAccessGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"administrator","type":"address"},{"indexed":false,"internalType":"bool","name":"_paused","type":"bool"}],"name":"StatePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"},{"indexed":false,"internalType":"uint256","name":"_token","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalTokenSent","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"_tokenSentToLinkedChainHash","type":"bytes32"}],"name":"TokenSentToLinkedChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenTransferredToOtherChain","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"transferHash","type":"bytes32"}],"name":"TokenTransferredToOtherChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"},{"indexed":false,"internalType":"uint256","name":"_token","type":"uint256"}],"name":"TransferredTokenClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"blackList","type":"address"}],"name":"TransfersDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"whiteList","type":"address"}],"name":"TransfersEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"WithdrawLimitUpdated","type":"event"},{"constant":true,"inputs":[],"name":"_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_activateMarket","type":"bytes32"}],"name":"activateMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"add24HoursWithdrawn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"administrator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_deActivateMarket","type":"bytes32"}],"name":"deActivateMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"denyAccess","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"disableFastWithdraws","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"disableTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"enableTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fastTransfersEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAdministrator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"getAllowance","outputs":[{"internalType":"uint256","name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_balance","type":"uint256"}],"name":"getBalanceHash","outputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"getBridgeNonce","outputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getCanTransfer","outputs":[{"internalType":"bool","name":"_hasAccess","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_mappingIndex","type":"uint256"}],"name":"getExposureMappingAddress","outputs":[{"internalType":"address","name":"_address","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"}],"name":"getExposureMappingIndex","outputs":[{"internalType":"uint256","name":"_mappingIndex","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getGovernance","outputs":[{"internalType":"address","name":"_governanceContract","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getLastRequestBlock","outputs":[{"internalType":"uint256","name":"_lastRequestBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getLastUpdated","outputs":[{"internalType":"uint256","name":"_lastUpdated","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getLiquidationPrice","outputs":[{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getLongShares","outputs":[{"internalType":"uint256","name":"_longShares","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMainChainWithdrawLimit","outputs":[{"internalType":"uint256","name":"_mainChainWithdrawLimit24","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMarketActive","outputs":[{"internalType":"bool","name":"_active","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMaxMappingIndex","outputs":[{"internalType":"uint256","name":"_maxMappingIndex","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMaximumLeverage","outputs":[{"internalType":"uint256","name":"_maxLeverage","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMeanEntryLeverage","outputs":[{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMeanEntryPrice","outputs":[{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMeanEntrySpread","outputs":[{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMorpherBridge","outputs":[{"internalType":"address","name":"_currentBridge","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getNumberOfRequests","outputs":[{"internalType":"uint256","name":"_numberOfRequests","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNumberOfRequestsLimit","outputs":[{"internalType":"uint256","name":"_numberOfRequestsLimit","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracleContract","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"_longShares","type":"uint256"},{"internalType":"uint256","name":"_shortShares","type":"uint256"},{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"},{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_positionHash","type":"bytes32"}],"name":"getPositionClaimedOnMainChain","outputs":[{"internalType":"bool","name":"_alreadyClaimed","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"internalType":"uint256","name":"_longShares","type":"uint256"},{"internalType":"uint256","name":"_shortShares","type":"uint256"},{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"},{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"name":"getPositionHash","outputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getShortShares","outputs":[{"internalType":"uint256","name":"_shortShares","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSideChainMerkleRoot","outputs":[{"internalType":"bytes32","name":"_sideChainMerkleRoot","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSideChainMerkleRootWrittenAtTime","outputs":[{"internalType":"uint256","name":"_sideChainMerkleRoot","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSideChainOperator","outputs":[{"internalType":"address","name":"_address","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getStateAccess","outputs":[{"internalType":"bool","name":"_hasAccess","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getTokenClaimedOnThisChain","outputs":[{"internalType":"uint256","name":"_token","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTokenContract","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getTokenSentToLinkedChain","outputs":[{"internalType":"uint256","name":"_token","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getTokenSentToLinkedChainTime","outputs":[{"internalType":"uint256","name":"_timeStamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"grantAccess","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"inactivityPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"increaseNumberOfRequests","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"last24HoursAmountWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastRewardTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastWithdrawLimitReductionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mainChain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mainChainWithdrawLimit24","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maximumLeverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"morpherBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"morpherGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"morpherRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"morpherToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numberOfRequestsLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracleContract","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[],"name":"pauseState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"payOperatingReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"resetLast24HoursAmountWithdrawn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewardBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"set24HourWithdrawLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newAdministrator","type":"address"}],"name":"setAdministrator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"setAllowance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setExposureMapping","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setExposureMappingAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setExposureMappingIndex","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newGovernanceContractAddress","type":"address"}],"name":"setGovernanceContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_periodLength","type":"uint256"}],"name":"setInactivityPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setLastRequestBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_mainChainWithdrawLimit24","type":"uint256"}],"name":"setMainChainWithdrawLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_maxMappingIndex","type":"uint256"}],"name":"setMaxMappingIndex","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_newMaximumLeverage","type":"uint256"}],"name":"setMaximumLeverage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newBridge","type":"address"}],"name":"setMorpherBridge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_numberOfRequests","type":"uint256"}],"name":"setNumberOfRequests","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_numberOfRequestsLimit","type":"uint256"}],"name":"setNumberOfRequestsLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newOracleContract","type":"address"}],"name":"setOracleContract","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":"_timeStamp","type":"uint256"},{"internalType":"uint256","name":"_longShares","type":"uint256"},{"internalType":"uint256","name":"_shortShares","type":"uint256"},{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"},{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"name":"setPosition","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_positionHash","type":"bytes32"}],"name":"setPositionClaimedOnMainChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newRewardsAddress","type":"address"}],"name":"setRewardAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_newRewardBasisPoints","type":"uint256"}],"name":"setRewardBasisPoints","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_sideChainMerkleRoot","type":"bytes32"}],"name":"setSideChainMerkleRoot","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setSideChainOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"setTokenClaimedOnThisChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newTokenContract","type":"address"}],"name":"setTokenContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"setTokenSentToLinkedChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_totalInPositions","type":"uint256"}],"name":"setTotalInPositions","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_newTotalOnOtherChain","type":"uint256"}],"name":"setTotalOnOtherChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sideChainMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sideChainMerkleRootWrittenAtTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sideChainOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalInPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalOnOtherChain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","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":true,"inputs":[],"name":"transferNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unPauseState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"update24HoursWithdrawLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawLimit24Hours","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]Contract Creation Code
6080604052633b9aca006005556006805460ff191690556a108b2a2c280290940000006011556203f4806020553480156200003957600080fd5b5060405162004e9838038062004e98833981810160405260608110156200005f57600080fd5b5080516020820151604092830151600080546001600160a01b031916331780825594519394929391926001600160a01b0316917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36000805460ff60a01b1916600160a01b85151502179055620000d9426200038c565b6b01dba0fc757e49bc9f0000006b015f8d402a52368049000000620001196200010a6001600160e01b03620003bf16565b6001600160e01b03620003ce16565b6200013f620001306001600160e01b03620003bf16565b6001600160e01b036200047016565b600054600160a01b900460ff1662000235578160146000620001696001600160e01b03620003bf16565b6001600160a01b0316815260208101919091526040016000205560028290556200019b6001600160e01b03620003bf16565b6001600160a01b031660008051602062004ddd833981519152620001da620001cb6001600160e01b03620003bf16565b6001600160e01b036200050e16565b60408051918252602082018690528051918290030190a26200020660006001600160e01b036200052916565b6200021b60006001600160e01b036200065d16565b6200022f816001600160e01b036200070116565b62000304565b80601460006200024d6001600160e01b03620003bf16565b6001600160a01b0316815260208101919091526040016000205560028190556200027f6001600160e01b03620003bf16565b6001600160a01b031660008051602062004ddd833981519152620002af620001cb6001600160e01b03620003bf16565b60408051918252602082018590528051918290030190a2620002dc613a986001600160e01b036200052916565b620002f0836001600160e01b036200065d16565b62000304826001600160e01b036200070116565b6022805460ff191660011790556200032660036001600160e01b036200079a16565b620003476032600154816200033757fe5b046001600160e01b036200082a16565b6200035b846001600160e01b036200047016565b62000381620003726001600160e01b03620003bf16565b6001600160e01b03620008b116565b505050505062000a35565b600e81905560405181907fb11f7283fda904f54a0fc8af727d3bf56e40a6cbf7c8fbb177083f0a335152ed90600090a250565b6000546001600160a01b031690565b620003e16001600160e01b036200095016565b62000422576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19166001179055514392917f556646edb498605e1eaf0f4ab1619f3dbc4164f1cddc22ecae584e045838d13891a350565b620004836001600160e01b036200095016565b620004c4576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f07c5be40db03f5890f6ca87fc24a286cabbbd63a79791089701cb0b5eb71529890600090a250565b6001600160a01b031660009081526014602052604090205490565b6200053c6001600160e01b036200095016565b6200057d576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b600054600160a01b900460ff16151560011415620005de57613a98811115620005d85760405162461bcd60e51b815260040180806020018281038252604481526020018062004d5d6044913960600191505060405180910390fd5b6200061d565b80156200061d5760405162461bcd60e51b815260040180806020018281038252603e81526020018062004e3a603e913960400191505060405180910390fd5b600d81905560075460405182916001600160a01b0316907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b620006706001600160e01b036200095016565b620006b1576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b038316908117909155600d546040519091907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b600a546001600160a01b031633146200074c5760405162461bcd60e51b815260040180806020018281038252603d81526020018062004dfd603d913960400191505060405180910390fd5b6004819055620007646001600160e01b036200096116565b6040805182815290517f38e3203d00fb51f959df7882c56c583370da2f7abea215c09e83e7ffa61281d29181900360200190a150565b3360009081526012602052604090205460ff161515600114620007ef5760405162461bcd60e51b815260040180806020018281038252603c81526020018062004da1603c913960400191505060405180910390fd5b60258190556040805182815290517f8347cc6d3a3b991db61121237578d3a133ddf434ee43936f1c48d2c815eb0ab39181900360200190a150565b6200083d6001600160e01b036200095016565b6200087e576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b601181905560405181907f1177d9c2a77eb9dd45c02329c8e4924e44101d64dabf8024543b0ce26e622f3690600090a250565b620008c46001600160e01b036200095016565b62000905576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19169055514392917fa40f23a963aabba33c55679497d6dd6d9815feadbeb0b0ad39d1285beda16bdd91a350565b6000546001600160a01b0316331490565b6200099a60045462000986600354600254620009d360201b62003c1a1790919060201c565b620009d360201b62003c1a1790919060201c565b600181905560408051918252517f5b1767df4e2cc8a7b2716959e609e0cdd987c9b88ac27b7fc4be99435aa1673b9181900360200190a1565b60008282018381101562000a2e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6143188062000a456000396000f3fe608060405234801561001057600080fd5b50600436106106e05760003560e01c80637c995e9111610387578063bfde5730116101de578063e4974f8d1161010f578063f2fde38b116100ad578063faddee1411610087578063faddee1414611292578063fbfc50f6146112be578063fc89a4fc146112c6578063ff047c38146112e3576106e0565b8063f2fde38b1461125c578063f53d0a8e14611282578063f606a41a1461128a576106e0565b8063ebd164fb116100e9578063ebd164fb146111c1578063ef5fa322146111e7578063ef92f83114611213578063efeecb0414611230576106e0565b8063e4974f8d14611194578063e4bd85221461119c578063e5160f80146111a4576106e0565b8063d8d5470d1161017c578063dc39d06d11610156578063dc39d06d1461110e578063df8089ef1461113a578063e291f13514611160578063e3bbb5651461118c576106e0565b8063d8d5470d146110b3578063da46098c146110bb578063da4b0f40146110f1576106e0565b8063c5e1b59a116101b8578063c5e1b59a14611060578063d362bd2b14611086578063d69082c41461108e578063d7118351146110ab576106e0565b8063bfde573014611015578063c209afac1461101d578063c5d90a1914611043576106e0565b8063aa43ced8116102b8578063b8ed12a411610256578063bcc3e34211610230578063bcc3e34214610f59578063be7e64b614610f7f578063beabacc814610fd7578063bece75321461100d576106e0565b8063b8ed12a414610f23578063bb65b24214610f2b578063bbcd5bbe14610f33576106e0565b8063acb17ba711610292578063acb17ba714610ebb578063af434a6d14610ee1578063b2bdfa7b14610efe578063b6554c2c14610f06576106e0565b8063aa43ced814610e8e578063aa7bcd5d14610e96578063ac981b1e14610e9e576106e0565b80639231cf7411610325578063a0580880116102ff578063a058088014610e2f578063a35ab9c814610e37578063a8c8afaa14610e54578063a99d389f14610e5c576106e0565b80639231cf7414610dde5780639dc29fac14610de65780639fe4e9d214610e12576106e0565b80638da5cb5b116103615780638da5cb5b14610d765780638ea09da614610d7e5780638f32d59b14610da45780639162298f14610dac576106e0565b80637c995e9114610d3a578063857b0da014610d425780638c4050b114610d6e576106e0565b80633d7f4f3c1161053b57806361afd5ac1161046c578063706277da1161040a57806373ed1fe2116103e457806373ed1fe214610cca578063755ca87a14610cd25780637a68744414610cda5780637b431ab114610d32576106e0565b8063706277da14610c9457806370a0823114610c9c578063715018a614610cc2576106e0565b806369c66c7b1161044657806369c66c7b14610c1757806369cdcfb714610c435780636c36a4ec14610c605780636d37e21814610c8c576106e0565b806361afd5ac14610bbd578063626be56714610be3578063652f176314610beb576106e0565b80634da3c199116104d95780635996e209116104b35780635996e20914610b615780635c8b933414610b695780635c975abb14610b8f5780635e00e67914610b97576106e0565b80634da3c19914610b3457806355b3374114610b51578063592b6aab14610b59576106e0565b8063422cc2e711610515578063422cc2e714610aa857806344ae029c14610ad4578063496ccd9b14610af15780634a4cce9714610b17576106e0565b80633d7f4f3c14610a485780633eedf76a14610a7457806340c10f1914610a7c576106e0565b8063169674071161061557806321c02c8e116105b357806328b7bede1161058d57806328b7bede146109cb5780632d7b42c1146109d35780633383e8d8146109f6578063364ae26e14610a22576106e0565b806321c02c8e1461099557806325fbf712146109bb578063289b3c0d146109c3576106e0565b80631864ba30116105ef5780631864ba30146109365780631bdbae90146109625780631cb110771461096a5780632020e69714610972576106e0565b806316967407146108f4578063174c51dc146108fc57806318160ddd1461092e576106e0565b80630b7c8e7f116106825780630fa8f5161161065c5780630fa8f516146108235780631129753f1461088257806314712512146108a857806314ce70ef146108ce576106e0565b80630b7c8e7f146107d95780630eb933dc146107e15780630f508e001461081b576106e0565b806309089f97116106be57806309089f97146107475780630aa7cee2146107615780630ae5e739146107855780630af4187d146107ab576106e0565b806304371f48146106e557806306442d0a1461070457806307a9100e14610721575b600080fd5b610702600480360360208110156106fb57600080fd5b50356112eb565b005b6107026004803603602081101561071a57600080fd5b503561140c565b6107026004803603602081101561073757600080fd5b50356001600160a01b03166114a3565b61074f611512565b60408051918252519081900360200190f35b6107696115af565b604080516001600160a01b039092168252519081900360200190f35b6107026004803603602081101561079b57600080fd5b50356001600160a01b03166115be565b61074f600480360360408110156107c157600080fd5b506001600160a01b0381358116916020013516611653565b61074f611680565b610807600480360360208110156107f757600080fd5b50356001600160a01b0316611686565b604080519115158252519081900360200190f35b6107696116a4565b61084f6004803603604081101561083957600080fd5b506001600160a01b0381351690602001356116b3565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b6107026004803603602081101561089857600080fd5b50356001600160a01b0316611700565b610807600480360360208110156108be57600080fd5b50356001600160a01b0316611799565b610702600480360360208110156108e457600080fd5b50356001600160a01b03166117b7565b610769611848565b6107026004803603606081101561091257600080fd5b508035906001600160a01b036020820135169060400135611857565b61074f6118e7565b61074f6004803603604081101561094c57600080fd5b506001600160a01b0381351690602001356118ed565b61074f611918565b61074f61191e565b6107026004803603604081101561098857600080fd5b5080359060200135611924565b61074f600480360360208110156109ab57600080fd5b50356001600160a01b0316611989565b61074f6119a4565b6107696119aa565b6107696119be565b610769600480360360408110156109e957600080fd5b50803590602001356119cd565b61070260048036036040811015610a0c57600080fd5b506001600160a01b0381351690602001356119f7565b61074f60048036036020811015610a3857600080fd5b50356001600160a01b0316611aa7565b61074f60048036036040811015610a5e57600080fd5b506001600160a01b038135169060200135611ac2565b61074f611aea565b61070260048036036040811015610a9257600080fd5b506001600160a01b038135169060200135611af0565b61070260048036036040811015610abe57600080fd5b506001600160a01b038135169060200135611d14565b61080760048036036020811015610aea57600080fd5b5035611dfa565b61070260048036036020811015610b0757600080fd5b50356001600160a01b0316611e0f565b61080760048036036020811015610b2d57600080fd5b5035611eb0565b61070260048036036020811015610b4a57600080fd5b5035611ec5565b61074f611f53565b610702611f59565b610702611fe5565b61074f60048036036020811015610b7f57600080fd5b50356001600160a01b0316612083565b61080761209e565b61070260048036036020811015610bad57600080fd5b50356001600160a01b03166120a7565b61070260048036036020811015610bd357600080fd5b50356001600160a01b031661213e565b61074f6121d0565b61074f60048036036040811015610c0157600080fd5b506001600160a01b0381351690602001356121d6565b61074f60048036036040811015610c2d57600080fd5b50803590602001356001600160a01b0316612201565b61070260048036036020811015610c5957600080fd5b503561222d565b61070260048036036040811015610c7657600080fd5b506001600160a01b0381351690602001356122a7565b610702612316565b61076961242b565b61074f60048036036020811015610cb257600080fd5b50356001600160a01b031661243a565b610702612455565b6107696124e6565b61074f6124f5565b61074f6004803603610120811015610cf157600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e08101359061010001356124fb565b61074f612573565b61074f612579565b61074f60048036036040811015610d5857600080fd5b506001600160a01b03813516906020013561257f565b61074f6125c3565b6107696125c9565b61070260048036036020811015610d9457600080fd5b50356001600160a01b03166125d8565b610807612668565b61070260048036036060811015610dc257600080fd5b508035906001600160a01b036020820135169060400135612679565b61074f6126e7565b61070260048036036040811015610dfc57600080fd5b506001600160a01b0381351690602001356126ed565b61070260048036036020811015610e2857600080fd5b503561292d565b6107026129bb565b61070260048036036020811015610e4d57600080fd5b5035612a42565b610769612b0c565b61070260048036036060811015610e7257600080fd5b508035906001600160a01b036020820135169060400135612b20565b61074f612b9d565b61074f612ba3565b61070260048036036020811015610eb457600080fd5b5035612ba9565b61070260048036036020811015610ed157600080fd5b50356001600160a01b0316612c43565b61070260048036036020811015610ef757600080fd5b5035612cd6565b610769612d69565b61070260048036036020811015610f1c57600080fd5b5035612d78565b61074f612dea565b61074f612df0565b61070260048036036020811015610f4957600080fd5b50356001600160a01b0316612df6565b61070260048036036020811015610f6f57600080fd5b50356001600160a01b0316612e87565b6107026004803603610120811015610f9657600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e0810135906101000135612efa565b61070260048036036060811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060400135613091565b6107696133a3565b6108076133b2565b61074f6004803603602081101561103357600080fd5b50356001600160a01b03166133c2565b6107026004803603602081101561105957600080fd5b50356133dd565b6107026004803603602081101561107657600080fd5b50356001600160a01b0316613469565b61074f613504565b610702600480360360208110156110a457600080fd5b503561350a565b6107026135ba565b61080761365e565b610702600480360360608110156110d157600080fd5b506001600160a01b03813581169160208101359091169060400135613667565b6107026004803603602081101561110757600080fd5b503561371c565b6108076004803603604081101561112457600080fd5b506001600160a01b0381351690602001356137f0565b6107026004803603602081101561115057600080fd5b50356001600160a01b03166138d3565b61074f6004803603604081101561117657600080fd5b506001600160a01b038135169060200135613974565b61076961399f565b6107696139ae565b61074f6139bd565b610702600480360360208110156111ba57600080fd5b50356139c3565b61074f600480360360208110156111d757600080fd5b50356001600160a01b0316613a5d565b61074f600480360360408110156111fd57600080fd5b506001600160a01b038135169060200135613a78565b61074f6004803603602081101561122957600080fd5b5035613aa3565b61074f6004803603604081101561124657600080fd5b506001600160a01b038135169060200135613ab5565b6107026004803603602081101561127257600080fd5b50356001600160a01b0316613ae0565b610769613b33565b610769613b42565b61074f600480360360408110156112a857600080fd5b506001600160a01b038135169060200135613b51565b61074f613b7c565b610702600480360360208110156112dc57600080fd5b5035613b82565b61074f613c14565b6112f3612668565b611332576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600054600160a01b900460ff1615156001141561138f57613a9881111561138a5760405162461bcd60e51b81526004018080602001828103825260448152602001806140876044913960600191505060405180910390fd5b6113cc565b80156113cc5760405162461bcd60e51b815260040180806020018281038252603e815260200180614227603e913960400191505060405180910390fd5b600d81905560075460405182916001600160a01b0316907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b611414611848565b6001600160a01b0316336001600160a01b0316146114635760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191690555182917f9cb9d54a58b209894faa9f115e54b1c61733c0764fe29ed01f97c7c425f2f24391a250565b3360009081526012602052604090205460ff1615156001146114f65760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03166000908152602360205260409020439055565b600061151c6124e6565b6001600160a01b0316336001600160a01b03161461156b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b602180546001019081905560408051918252517f86423ef8971dc4252acb273ac1099fb639020a7a2f5a64dad077d033ab2ae8e29181900360200190a15060215490565b600a546001600160a01b031681565b6115c6612668565b611605576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19166001179055514392917f556646edb498605e1eaf0f4ab1619f3dbc4164f1cddc22ecae584e045838d13891a350565b6001600160a01b038083166000908152601560209081526040808320938516835292905220545b92915050565b60035481565b6001600160a01b031660009081526013602052604090205460ff1690565b600a546001600160a01b031690565b6001600160a01b0391909116600090815260176020908152604080832093835292905220600181015460028201546003830154600484015460058501546006909501549395929491939092565b611708612668565b611747576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b60068054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f5ab1e8b2c0a96bffa69cb323894590e00556bdce76b87d529100949740e6a55a90600090a250565b6001600160a01b031660009081526012602052604090205460ff1690565b6117bf612668565b6117fe576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f07c5be40db03f5890f6ca87fc24a286cabbbd63a79791089701cb0b5eb71529890600090a250565b6008546001600160a01b031690565b3360009081526012602052604090205460ff1615156001146118aa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085209285526002909201905290912080546001600160a01b0319166001600160a01b03909216919091179055565b60015481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206002015490565b60045481565b601f5481565b3360009081526012602052604090205460ff1615156001146119775760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009182526018602052604090912055565b6001600160a01b031660009081526019602052604090205490565b600f5490565b60065461010090046001600160a01b031690565b600c546001600160a01b031690565b6000918252601860209081526040808420928452600290920190529020546001600160a01b031690565b6119ff6124e6565b6001600160a01b0316336001600160a01b031614611a4e5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000818152601960209081526040918290208490558151928352820183905280517fb83fc1206022cf828cdd927bea92f3cfe9ae485bc4d4308b65413dfdd0ab6edb9281900390910190a15050565b6001600160a01b03166000908152601a602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052205490565b60055481565b3360009081526012602052604090205460ff161515600114611b435760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff1615611b855760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038216600090815260146020526040902054611bae908263ffffffff613c1a16565b6001600160a01b038316600090815260146020526040902055600254611bda908263ffffffff613c1a16565b600255611be5613c7b565b600c54604080516323de665160e01b81526000600482018190526001600160a01b03868116602484015260448301869052925192909316926323de66519260648084019382900301818387803b158015611c3e57600080fd5b505af1158015611c52573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a35050565b611d1c6124e6565b6001600160a01b0316336001600160a01b031614611d6b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000908152601a60208181526040808420858155601b835293204290555254611d9f90839061257f565b6001600160a01b0383166000818152601a602090815260409182902054825193845290830185905282820152517fa3579111956ed8ebf7836e375375f707ea762883fa60008df45a289d53090b659181900360600190a25050565b6000908152601c602052604090205460ff1690565b611e176119aa565b6001600160a01b0316336001600160a01b031614611e665760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040517f127863dda9b4c03043886af0affd8e8ff8c0c65822d70f0b639eadce57271f0890600090a250565b60009081526016602052604090205460ff1690565b611ecd6124e6565b6001600160a01b0316336001600160a01b031614611f1c5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b600f8190554260105560405181907f2fe11f024562cd0798f5b3975c7be128c3b86e0249f9a66ad1e74bfb52f9246490600090a250565b60115481565b611f616124e6565b6001600160a01b0316336001600160a01b031614611fb05760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6022805460ff191690556040517ff6b2b9c63998bbfbe0a548dce3fa97702cb864dbfbdb42d4bcdb6f58c4209c3490600090a1565b611fed611848565b6001600160a01b0316336001600160a01b03161461203c5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff19169055604080513381526000602082015281517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c2929181900390910190a1565b6001600160a01b031660009081526024602052604090205490565b60065460ff1681565b6120af612668565b6120ee576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b038316908117909155600d546040519091907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b612146612668565b612185576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19169055514392917fa40f23a963aabba33c55679497d6dd6d9815feadbeb0b0ad39d1285beda16bdd91a350565b60025481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206006015490565b60008281526018602090815260408083206001600160a01b038516845260010190915290205492915050565b612235612668565b612274576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b601181905560405181907f1177d9c2a77eb9dd45c02329c8e4924e44101d64dabf8024543b0ce26e622f3690600090a250565b3360009081526012602052604090205460ff1615156001146122fa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03909116600090815260246020526040902055565b600054600160a01b900460ff1615156001146123635760405162461bcd60e51b815260040180806020018281038252602e815260200180614173602e913960400191505060405180910390fd5b600e54612379906201518063ffffffff613c1a16565b4211156124295760006123ad6305f5e1006123a1600d54600154613cdd90919063ffffffff16565b9063ffffffff613d3616565b90506123cf6123ca62015180600e54613c1a90919063ffffffff16565b613d78565b6007546123e5906001600160a01b031682611af0565b6007546040805183815290516001600160a01b03909216917f38fec7f72e65a01ab4170fddd9ed4438b1b378e84bef08292112fb619abfc9a29181900360200190a2505b565b600c546001600160a01b031681565b6001600160a01b031660009081526014602052604090205490565b61245d612668565b61249c576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600b546001600160a01b031690565b60255490565b6040805160609a909a1b6bffffffffffffffffffffffff19166020808c019190915260348b019990995260548a01979097526074890195909552609488019390935260b487019190915260d486015260f485015261011480850191909152815180850390910181526101349093019052815191012090565b60105481565b60055490565b6040805160609390931b6bffffffffffffffffffffffff19166020808501919091526034808501939093528151808503909301835260549093019052805191012090565b60255481565b6000546001600160a01b031690565b6125e0612668565b61261f576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19169055517f972d3365ef4d458e53aedba4b7422b4eea3046ea55b243b9e64341b1f1ad449d9190a250565b6000546001600160a01b0316331490565b3360009081526012602052604090205460ff1615156001146126cc5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6126d7838383612b20565b6126e2838383611857565b505050565b600e5481565b3360009081526012602052604090205460ff1615156001146127405760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156127825760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b0382166000908152601460205260409020548111156127ef576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b038216600090815260146020526040902054612818908263ffffffff613dab16565b6001600160a01b038316600090815260146020526040902055600254612844908263ffffffff613dab16565b60025561284f613c7b565b600c54604080516323de665160e01b81526001600160a01b0385811660048301526000602483018190526044830186905292519316926323de66519260648084019391929182900301818387803b1580156128a957600080fd5b505af11580156128bd573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b3360009081526012602052604090205460ff1615156001146129805760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60258190556040805182815290517f8347cc6d3a3b991db61121237578d3a133ddf434ee43936f1c48d2c815eb0ab39181900360200190a150565b6129c36124e6565b6001600160a01b0316336001600160a01b031614612a125760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000601e8190556040517fcada5cc63a6cd5770ca818284aa0ee429013dfd689c4f9587022943b408a09b19190a1565b612a4a6124e6565b6001600160a01b0316336001600160a01b031614612a995760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b80601e541115612abe57601e54612ab6908263ffffffff613dab16565b601e55612ac4565b6000601e555b42601d819055601e5460408051918252602082019290925281517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a0929181900390910190a150565b60065461010090046001600160a01b031681565b3360009081526012602052604090205460ff161515600114612b735760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085206001600160a01b03909416855260019093019052912055565b601d5481565b601e5481565b612bb1611848565b6001600160a01b0316336001600160a01b031614612c005760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191660011790555182917f52ebf9d662e8bc70841a5b603c1711882a8e4b11a663af6b5709286fe7bd964591a250565b612c4b612668565b612c8a576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19166001179055517f6d3bdb877ca7bde5be7e4afec9b4afd12e4f3dd1188c8fa57a7802f0f6cfa4d49190a250565b612cde6124e6565b6001600160a01b0316336001600160a01b031614612d2d5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b60208181556040805183815290517faf1ea5ac33bf092763f62a127ef50006ae56eef9cc122568bea97c7308d17376929181900390910190a150565b6000546001600160a01b031681565b612d806124e6565b6001600160a01b0316336001600160a01b031614612dcf5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000908152601c60205260409020805460ff19166001179055565b60215481565b600d5481565b612dfe612668565b612e3d576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040517f0e6436d2b3e53a8a3ec2fbdd1d22525f0cd81d796bcb4beeef7337031a7e5efa90600090a250565b3360009081526012602052604090205460ff161515600114612eda5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b0316600090815260246020526040902080546001019055565b3360009081526012602052604090205460ff161515600114612f4d5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03891660009081526017602090815260408083208b845290915290208781556001810187905560028101869055600381018590556004810184905560058101839055600601819055612fad8989898989898989896124fb565b6001600160a01b038a1660009081526017602090815260408083208c845290915290206007015585151580612fe25750600085115b15612ff657612ff1888a613ded565b613000565b613000888a613e2d565b6001600160a01b03891660008181526017602090815260408083208c84528252918290206007015482518b81529182018a9052818301899052606082018890526080820187905260a0820186905260c0820185905291518b9392917f35ea872e77adbec19df83a66765d5bdc0adfe73d9ada9518cb384242ddb40d5d919081900360e00190a4505050505050505050565b3360009081526012602052604090205460ff1615156001146130e45760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156131265760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038316600090815260146020526040902054811115613193576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b0383166000908152601460205260409020546131bc908263ffffffff613dab16565b6001600160a01b0380851660009081526014602052604080822093909355908416815220546131f1908263ffffffff613c1a16565b6001600160a01b0380841660008181526014602052604080822094909455600c5484516323de665160e01b81528885166004820152602481019390935260448301869052935193909216926323de66519260648084019391929182900301818387803b15801561326057600080fd5b505af1158015613274573d6000803e3d6000fd5b50506040805184815290516001600160a01b038087169450871692507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a36001600160a01b0383166000908152601460205260409020546132de90849061257f565b6001600160a01b03841660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a36001600160a01b03821660009081526014602052604090205461335090839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a3505050565b6009546001600160a01b031681565b600054600160a01b900460ff1681565b6001600160a01b031660009081526023602052604090205490565b600a546001600160a01b031633146134265760405162461bcd60e51b815260040180806020018281038252603d8152602001806141ea603d913960400191505060405180910390fd5b6004819055613433613c7b565b6040805182815290517f38e3203d00fb51f959df7882c56c583370da2f7abea215c09e83e7ffa61281d29181900360200190a150565b613471612668565b6134b0576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600b80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f631bdf9495e4e83ab921eecb28e1057d3598a3fa0fc5f40b06bafe3e7333bc5c9181900360200190a150565b60205481565b6135126124e6565b6001600160a01b0316336001600160a01b0316146135615760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601e54613574908263ffffffff613c1a16565b601e819055601d5460408051928352602083019190915280517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a09281900390910190a150565b6135c2611848565b6001600160a01b0316336001600160a01b0316146136115760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff1916600190811790915560408051338152602081019290925280517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c29281900390910190a1565b60225460ff1681565b3360009081526012602052604090205460ff1615156001146136ba5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03808416600081815260156020908152604080832094871680845294825291829020859055815185815291517f3c07380f6fcae3bac39771c60e5c680334073911f2176b65f1d6925ba0badcdf9281900390910190a3505050565b613724611848565b6001600160a01b0316336001600160a01b0316146137735760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6305f5e10081116137b55760405162461bcd60e51b81526004018080602001828103825260278152602001806141076027913960400191505060405180910390fd5b60058190556040805182815290517f258a1584bca0aad852538c9d396233520174feedba906a03d19b307d3bad5f309181900360200190a150565b60006137fa612668565b613839576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6138506125c9565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156138a057600080fd5b505af11580156138b4573d6000803e3d6000fd5b505050506040513d60208110156138ca57600080fd5b50519392505050565b6138db6119aa565b6001600160a01b0316336001600160a01b03161461392a5760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040517f47c6cd80582c55aabfec5a8be39d30b380cf41ba92dd2d13ba626c48c96bf27690600090a250565b6001600160a01b03919091166000908152601760209081526040808320938352929052206003015490565b6009546001600160a01b031690565b600b546001600160a01b031681565b60105490565b6139cb611848565b6001600160a01b0316336001600160a01b031614613a1a5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6003819055613a27613c7b565b6040805182815290517ff915189a6212c055e85c9c0dc760b7a2a5d1ff9a9e64bd9af0a9897b4046dcd99181900360200190a150565b6001600160a01b03166000908152601b602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206001015490565b60009081526018602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206004015490565b613ae8612668565b613b27576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b613b3081613eb9565b50565b6008546001600160a01b031681565b6007546001600160a01b031681565b6001600160a01b03919091166000908152601760209081526040808320938352929052206005015490565b600f5481565b613b8a6124e6565b6001600160a01b0316336001600160a01b031614613bd95760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601f8190556040805182815290517f0969f79b044617688492c7c9b226129947037ca88c450002a7561ed78aa549ac9181900360200190a150565b60115490565b600082820183811015613c74576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b613ca4600454613c98600354600254613c1a90919063ffffffff16565b9063ffffffff613c1a16565b600181905560408051918252517f5b1767df4e2cc8a7b2716959e609e0cdd987c9b88ac27b7fc4be99435aa1673b9181900360200190a1565b600082613cec5750600061167a565b82820282848281613cf957fe5b0414613c745760405162461bcd60e51b81526004018080602001828103825260218152602001806141c96021913960400191505060405180910390fd5b6000613c7483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f59565b600e81905560405181907fb11f7283fda904f54a0fc8af727d3bf56e40a6cbf7c8fbb177083f0a335152ed90600090a250565b6000613c7483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613ffb565b6000613df98383612201565b9050806126e2576000613e106001613c9886613aa3565b9050613e1c8482611924565b613e27848483612679565b50505050565b6000613e398383612201565b90506000613e4684613aa3565b90506000613e5485836119cd565b90508215613eb25781831015613e7a57613e6f858285611857565b613e7a858285612b20565b613e8685600084611857565b613e9285856000612b20565b8115613eb257613eb285613ead84600163ffffffff613dab16565b611924565b5050505050565b6001600160a01b038116613efe5760405162461bcd60e51b81526004018080602001828103825260288152602001806141a16028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008183613fe55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613faa578181015183820152602001613f92565b50505050905090810190601f168015613fd75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613ff157fe5b0495945050505050565b6000818484111561404d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613faa578181015183820152602001613f92565b50505090039056fe4d6f727068657253746174653a2043616c6c6572206973206e6f7420746865204272696467652e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e7473206e65656420746f206265206c657373206f7220657175616c20746f2031353030302e4d6f727068657253746174653a204f6e6c7920506c6174666f726d20697320616c6c6f77656420746f2065786563757465206f7065726174696f6e2e4d6f727068657253746174653a204c6576657261676520707265636973696f6e206973203165384d6f727068657253746174653a2043616c6c696e6720636f6e7472616374206e6f742074686520476f7665726e616e636520436f6e74726163742e2041626f7274696e672e4d6f727068657253746174653a2043616e206f6e6c792062652063616c6c6564206f6e206d61696e636861696e2e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f727068657253746174653a2043616c6c6572206973206e6f74207468652053696465636861696e204f70657261746f722e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e74732063616e206f6e6c7920626520736574206f6e20457468657265756d2e4d6f727068657253746174653a2043616c6c6572206973206e6f74207468652041646d696e6973747261746f722e2041626f7274696e672e4d6f727068657253746174653a20436f6e7472616374207061757365642c2061626f7274696e674f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722ea265627a7a72315820160459360f99868cb32b4e506044eeea98d9c28ae8691a9461867be3f47ceaa764736f6c634300051000324d6f727068657253746174653a2052657761726420626173697320706f696e7473206e65656420746f206265206c657373206f7220657175616c20746f2031353030302e4d6f727068657253746174653a204f6e6c7920506c6174666f726d20697320616c6c6f77656420746f2065786563757465206f7065726174696f6e2e4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f4d6f727068657253746174653a2043616c6c6572206973206e6f74207468652053696465636861696e204f70657261746f722e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e74732063616e206f6e6c7920626520736574206f6e20457468657265756d2e4f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070dcdb66e128738189012dee12d7e13b377a1d3b000000000000000000000000e261d68bda5bd518598e31320ede6e1e2d53682f
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106106e05760003560e01c80637c995e9111610387578063bfde5730116101de578063e4974f8d1161010f578063f2fde38b116100ad578063faddee1411610087578063faddee1414611292578063fbfc50f6146112be578063fc89a4fc146112c6578063ff047c38146112e3576106e0565b8063f2fde38b1461125c578063f53d0a8e14611282578063f606a41a1461128a576106e0565b8063ebd164fb116100e9578063ebd164fb146111c1578063ef5fa322146111e7578063ef92f83114611213578063efeecb0414611230576106e0565b8063e4974f8d14611194578063e4bd85221461119c578063e5160f80146111a4576106e0565b8063d8d5470d1161017c578063dc39d06d11610156578063dc39d06d1461110e578063df8089ef1461113a578063e291f13514611160578063e3bbb5651461118c576106e0565b8063d8d5470d146110b3578063da46098c146110bb578063da4b0f40146110f1576106e0565b8063c5e1b59a116101b8578063c5e1b59a14611060578063d362bd2b14611086578063d69082c41461108e578063d7118351146110ab576106e0565b8063bfde573014611015578063c209afac1461101d578063c5d90a1914611043576106e0565b8063aa43ced8116102b8578063b8ed12a411610256578063bcc3e34211610230578063bcc3e34214610f59578063be7e64b614610f7f578063beabacc814610fd7578063bece75321461100d576106e0565b8063b8ed12a414610f23578063bb65b24214610f2b578063bbcd5bbe14610f33576106e0565b8063acb17ba711610292578063acb17ba714610ebb578063af434a6d14610ee1578063b2bdfa7b14610efe578063b6554c2c14610f06576106e0565b8063aa43ced814610e8e578063aa7bcd5d14610e96578063ac981b1e14610e9e576106e0565b80639231cf7411610325578063a0580880116102ff578063a058088014610e2f578063a35ab9c814610e37578063a8c8afaa14610e54578063a99d389f14610e5c576106e0565b80639231cf7414610dde5780639dc29fac14610de65780639fe4e9d214610e12576106e0565b80638da5cb5b116103615780638da5cb5b14610d765780638ea09da614610d7e5780638f32d59b14610da45780639162298f14610dac576106e0565b80637c995e9114610d3a578063857b0da014610d425780638c4050b114610d6e576106e0565b80633d7f4f3c1161053b57806361afd5ac1161046c578063706277da1161040a57806373ed1fe2116103e457806373ed1fe214610cca578063755ca87a14610cd25780637a68744414610cda5780637b431ab114610d32576106e0565b8063706277da14610c9457806370a0823114610c9c578063715018a614610cc2576106e0565b806369c66c7b1161044657806369c66c7b14610c1757806369cdcfb714610c435780636c36a4ec14610c605780636d37e21814610c8c576106e0565b806361afd5ac14610bbd578063626be56714610be3578063652f176314610beb576106e0565b80634da3c199116104d95780635996e209116104b35780635996e20914610b615780635c8b933414610b695780635c975abb14610b8f5780635e00e67914610b97576106e0565b80634da3c19914610b3457806355b3374114610b51578063592b6aab14610b59576106e0565b8063422cc2e711610515578063422cc2e714610aa857806344ae029c14610ad4578063496ccd9b14610af15780634a4cce9714610b17576106e0565b80633d7f4f3c14610a485780633eedf76a14610a7457806340c10f1914610a7c576106e0565b8063169674071161061557806321c02c8e116105b357806328b7bede1161058d57806328b7bede146109cb5780632d7b42c1146109d35780633383e8d8146109f6578063364ae26e14610a22576106e0565b806321c02c8e1461099557806325fbf712146109bb578063289b3c0d146109c3576106e0565b80631864ba30116105ef5780631864ba30146109365780631bdbae90146109625780631cb110771461096a5780632020e69714610972576106e0565b806316967407146108f4578063174c51dc146108fc57806318160ddd1461092e576106e0565b80630b7c8e7f116106825780630fa8f5161161065c5780630fa8f516146108235780631129753f1461088257806314712512146108a857806314ce70ef146108ce576106e0565b80630b7c8e7f146107d95780630eb933dc146107e15780630f508e001461081b576106e0565b806309089f97116106be57806309089f97146107475780630aa7cee2146107615780630ae5e739146107855780630af4187d146107ab576106e0565b806304371f48146106e557806306442d0a1461070457806307a9100e14610721575b600080fd5b610702600480360360208110156106fb57600080fd5b50356112eb565b005b6107026004803603602081101561071a57600080fd5b503561140c565b6107026004803603602081101561073757600080fd5b50356001600160a01b03166114a3565b61074f611512565b60408051918252519081900360200190f35b6107696115af565b604080516001600160a01b039092168252519081900360200190f35b6107026004803603602081101561079b57600080fd5b50356001600160a01b03166115be565b61074f600480360360408110156107c157600080fd5b506001600160a01b0381358116916020013516611653565b61074f611680565b610807600480360360208110156107f757600080fd5b50356001600160a01b0316611686565b604080519115158252519081900360200190f35b6107696116a4565b61084f6004803603604081101561083957600080fd5b506001600160a01b0381351690602001356116b3565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b6107026004803603602081101561089857600080fd5b50356001600160a01b0316611700565b610807600480360360208110156108be57600080fd5b50356001600160a01b0316611799565b610702600480360360208110156108e457600080fd5b50356001600160a01b03166117b7565b610769611848565b6107026004803603606081101561091257600080fd5b508035906001600160a01b036020820135169060400135611857565b61074f6118e7565b61074f6004803603604081101561094c57600080fd5b506001600160a01b0381351690602001356118ed565b61074f611918565b61074f61191e565b6107026004803603604081101561098857600080fd5b5080359060200135611924565b61074f600480360360208110156109ab57600080fd5b50356001600160a01b0316611989565b61074f6119a4565b6107696119aa565b6107696119be565b610769600480360360408110156109e957600080fd5b50803590602001356119cd565b61070260048036036040811015610a0c57600080fd5b506001600160a01b0381351690602001356119f7565b61074f60048036036020811015610a3857600080fd5b50356001600160a01b0316611aa7565b61074f60048036036040811015610a5e57600080fd5b506001600160a01b038135169060200135611ac2565b61074f611aea565b61070260048036036040811015610a9257600080fd5b506001600160a01b038135169060200135611af0565b61070260048036036040811015610abe57600080fd5b506001600160a01b038135169060200135611d14565b61080760048036036020811015610aea57600080fd5b5035611dfa565b61070260048036036020811015610b0757600080fd5b50356001600160a01b0316611e0f565b61080760048036036020811015610b2d57600080fd5b5035611eb0565b61070260048036036020811015610b4a57600080fd5b5035611ec5565b61074f611f53565b610702611f59565b610702611fe5565b61074f60048036036020811015610b7f57600080fd5b50356001600160a01b0316612083565b61080761209e565b61070260048036036020811015610bad57600080fd5b50356001600160a01b03166120a7565b61070260048036036020811015610bd357600080fd5b50356001600160a01b031661213e565b61074f6121d0565b61074f60048036036040811015610c0157600080fd5b506001600160a01b0381351690602001356121d6565b61074f60048036036040811015610c2d57600080fd5b50803590602001356001600160a01b0316612201565b61070260048036036020811015610c5957600080fd5b503561222d565b61070260048036036040811015610c7657600080fd5b506001600160a01b0381351690602001356122a7565b610702612316565b61076961242b565b61074f60048036036020811015610cb257600080fd5b50356001600160a01b031661243a565b610702612455565b6107696124e6565b61074f6124f5565b61074f6004803603610120811015610cf157600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e08101359061010001356124fb565b61074f612573565b61074f612579565b61074f60048036036040811015610d5857600080fd5b506001600160a01b03813516906020013561257f565b61074f6125c3565b6107696125c9565b61070260048036036020811015610d9457600080fd5b50356001600160a01b03166125d8565b610807612668565b61070260048036036060811015610dc257600080fd5b508035906001600160a01b036020820135169060400135612679565b61074f6126e7565b61070260048036036040811015610dfc57600080fd5b506001600160a01b0381351690602001356126ed565b61070260048036036020811015610e2857600080fd5b503561292d565b6107026129bb565b61070260048036036020811015610e4d57600080fd5b5035612a42565b610769612b0c565b61070260048036036060811015610e7257600080fd5b508035906001600160a01b036020820135169060400135612b20565b61074f612b9d565b61074f612ba3565b61070260048036036020811015610eb457600080fd5b5035612ba9565b61070260048036036020811015610ed157600080fd5b50356001600160a01b0316612c43565b61070260048036036020811015610ef757600080fd5b5035612cd6565b610769612d69565b61070260048036036020811015610f1c57600080fd5b5035612d78565b61074f612dea565b61074f612df0565b61070260048036036020811015610f4957600080fd5b50356001600160a01b0316612df6565b61070260048036036020811015610f6f57600080fd5b50356001600160a01b0316612e87565b6107026004803603610120811015610f9657600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e0810135906101000135612efa565b61070260048036036060811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060400135613091565b6107696133a3565b6108076133b2565b61074f6004803603602081101561103357600080fd5b50356001600160a01b03166133c2565b6107026004803603602081101561105957600080fd5b50356133dd565b6107026004803603602081101561107657600080fd5b50356001600160a01b0316613469565b61074f613504565b610702600480360360208110156110a457600080fd5b503561350a565b6107026135ba565b61080761365e565b610702600480360360608110156110d157600080fd5b506001600160a01b03813581169160208101359091169060400135613667565b6107026004803603602081101561110757600080fd5b503561371c565b6108076004803603604081101561112457600080fd5b506001600160a01b0381351690602001356137f0565b6107026004803603602081101561115057600080fd5b50356001600160a01b03166138d3565b61074f6004803603604081101561117657600080fd5b506001600160a01b038135169060200135613974565b61076961399f565b6107696139ae565b61074f6139bd565b610702600480360360208110156111ba57600080fd5b50356139c3565b61074f600480360360208110156111d757600080fd5b50356001600160a01b0316613a5d565b61074f600480360360408110156111fd57600080fd5b506001600160a01b038135169060200135613a78565b61074f6004803603602081101561122957600080fd5b5035613aa3565b61074f6004803603604081101561124657600080fd5b506001600160a01b038135169060200135613ab5565b6107026004803603602081101561127257600080fd5b50356001600160a01b0316613ae0565b610769613b33565b610769613b42565b61074f600480360360408110156112a857600080fd5b506001600160a01b038135169060200135613b51565b61074f613b7c565b610702600480360360208110156112dc57600080fd5b5035613b82565b61074f613c14565b6112f3612668565b611332576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600054600160a01b900460ff1615156001141561138f57613a9881111561138a5760405162461bcd60e51b81526004018080602001828103825260448152602001806140876044913960600191505060405180910390fd5b6113cc565b80156113cc5760405162461bcd60e51b815260040180806020018281038252603e815260200180614227603e913960400191505060405180910390fd5b600d81905560075460405182916001600160a01b0316907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b611414611848565b6001600160a01b0316336001600160a01b0316146114635760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191690555182917f9cb9d54a58b209894faa9f115e54b1c61733c0764fe29ed01f97c7c425f2f24391a250565b3360009081526012602052604090205460ff1615156001146114f65760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03166000908152602360205260409020439055565b600061151c6124e6565b6001600160a01b0316336001600160a01b03161461156b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b602180546001019081905560408051918252517f86423ef8971dc4252acb273ac1099fb639020a7a2f5a64dad077d033ab2ae8e29181900360200190a15060215490565b600a546001600160a01b031681565b6115c6612668565b611605576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19166001179055514392917f556646edb498605e1eaf0f4ab1619f3dbc4164f1cddc22ecae584e045838d13891a350565b6001600160a01b038083166000908152601560209081526040808320938516835292905220545b92915050565b60035481565b6001600160a01b031660009081526013602052604090205460ff1690565b600a546001600160a01b031690565b6001600160a01b0391909116600090815260176020908152604080832093835292905220600181015460028201546003830154600484015460058501546006909501549395929491939092565b611708612668565b611747576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b60068054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f5ab1e8b2c0a96bffa69cb323894590e00556bdce76b87d529100949740e6a55a90600090a250565b6001600160a01b031660009081526012602052604090205460ff1690565b6117bf612668565b6117fe576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f07c5be40db03f5890f6ca87fc24a286cabbbd63a79791089701cb0b5eb71529890600090a250565b6008546001600160a01b031690565b3360009081526012602052604090205460ff1615156001146118aa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085209285526002909201905290912080546001600160a01b0319166001600160a01b03909216919091179055565b60015481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206002015490565b60045481565b601f5481565b3360009081526012602052604090205460ff1615156001146119775760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009182526018602052604090912055565b6001600160a01b031660009081526019602052604090205490565b600f5490565b60065461010090046001600160a01b031690565b600c546001600160a01b031690565b6000918252601860209081526040808420928452600290920190529020546001600160a01b031690565b6119ff6124e6565b6001600160a01b0316336001600160a01b031614611a4e5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000818152601960209081526040918290208490558151928352820183905280517fb83fc1206022cf828cdd927bea92f3cfe9ae485bc4d4308b65413dfdd0ab6edb9281900390910190a15050565b6001600160a01b03166000908152601a602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052205490565b60055481565b3360009081526012602052604090205460ff161515600114611b435760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff1615611b855760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038216600090815260146020526040902054611bae908263ffffffff613c1a16565b6001600160a01b038316600090815260146020526040902055600254611bda908263ffffffff613c1a16565b600255611be5613c7b565b600c54604080516323de665160e01b81526000600482018190526001600160a01b03868116602484015260448301869052925192909316926323de66519260648084019382900301818387803b158015611c3e57600080fd5b505af1158015611c52573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a35050565b611d1c6124e6565b6001600160a01b0316336001600160a01b031614611d6b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000908152601a60208181526040808420858155601b835293204290555254611d9f90839061257f565b6001600160a01b0383166000818152601a602090815260409182902054825193845290830185905282820152517fa3579111956ed8ebf7836e375375f707ea762883fa60008df45a289d53090b659181900360600190a25050565b6000908152601c602052604090205460ff1690565b611e176119aa565b6001600160a01b0316336001600160a01b031614611e665760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040517f127863dda9b4c03043886af0affd8e8ff8c0c65822d70f0b639eadce57271f0890600090a250565b60009081526016602052604090205460ff1690565b611ecd6124e6565b6001600160a01b0316336001600160a01b031614611f1c5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b600f8190554260105560405181907f2fe11f024562cd0798f5b3975c7be128c3b86e0249f9a66ad1e74bfb52f9246490600090a250565b60115481565b611f616124e6565b6001600160a01b0316336001600160a01b031614611fb05760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6022805460ff191690556040517ff6b2b9c63998bbfbe0a548dce3fa97702cb864dbfbdb42d4bcdb6f58c4209c3490600090a1565b611fed611848565b6001600160a01b0316336001600160a01b03161461203c5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff19169055604080513381526000602082015281517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c2929181900390910190a1565b6001600160a01b031660009081526024602052604090205490565b60065460ff1681565b6120af612668565b6120ee576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b038316908117909155600d546040519091907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b612146612668565b612185576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19169055514392917fa40f23a963aabba33c55679497d6dd6d9815feadbeb0b0ad39d1285beda16bdd91a350565b60025481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206006015490565b60008281526018602090815260408083206001600160a01b038516845260010190915290205492915050565b612235612668565b612274576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b601181905560405181907f1177d9c2a77eb9dd45c02329c8e4924e44101d64dabf8024543b0ce26e622f3690600090a250565b3360009081526012602052604090205460ff1615156001146122fa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03909116600090815260246020526040902055565b600054600160a01b900460ff1615156001146123635760405162461bcd60e51b815260040180806020018281038252602e815260200180614173602e913960400191505060405180910390fd5b600e54612379906201518063ffffffff613c1a16565b4211156124295760006123ad6305f5e1006123a1600d54600154613cdd90919063ffffffff16565b9063ffffffff613d3616565b90506123cf6123ca62015180600e54613c1a90919063ffffffff16565b613d78565b6007546123e5906001600160a01b031682611af0565b6007546040805183815290516001600160a01b03909216917f38fec7f72e65a01ab4170fddd9ed4438b1b378e84bef08292112fb619abfc9a29181900360200190a2505b565b600c546001600160a01b031681565b6001600160a01b031660009081526014602052604090205490565b61245d612668565b61249c576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600b546001600160a01b031690565b60255490565b6040805160609a909a1b6bffffffffffffffffffffffff19166020808c019190915260348b019990995260548a01979097526074890195909552609488019390935260b487019190915260d486015260f485015261011480850191909152815180850390910181526101349093019052815191012090565b60105481565b60055490565b6040805160609390931b6bffffffffffffffffffffffff19166020808501919091526034808501939093528151808503909301835260549093019052805191012090565b60255481565b6000546001600160a01b031690565b6125e0612668565b61261f576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19169055517f972d3365ef4d458e53aedba4b7422b4eea3046ea55b243b9e64341b1f1ad449d9190a250565b6000546001600160a01b0316331490565b3360009081526012602052604090205460ff1615156001146126cc5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6126d7838383612b20565b6126e2838383611857565b505050565b600e5481565b3360009081526012602052604090205460ff1615156001146127405760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156127825760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b0382166000908152601460205260409020548111156127ef576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b038216600090815260146020526040902054612818908263ffffffff613dab16565b6001600160a01b038316600090815260146020526040902055600254612844908263ffffffff613dab16565b60025561284f613c7b565b600c54604080516323de665160e01b81526001600160a01b0385811660048301526000602483018190526044830186905292519316926323de66519260648084019391929182900301818387803b1580156128a957600080fd5b505af11580156128bd573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b3360009081526012602052604090205460ff1615156001146129805760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60258190556040805182815290517f8347cc6d3a3b991db61121237578d3a133ddf434ee43936f1c48d2c815eb0ab39181900360200190a150565b6129c36124e6565b6001600160a01b0316336001600160a01b031614612a125760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000601e8190556040517fcada5cc63a6cd5770ca818284aa0ee429013dfd689c4f9587022943b408a09b19190a1565b612a4a6124e6565b6001600160a01b0316336001600160a01b031614612a995760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b80601e541115612abe57601e54612ab6908263ffffffff613dab16565b601e55612ac4565b6000601e555b42601d819055601e5460408051918252602082019290925281517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a0929181900390910190a150565b60065461010090046001600160a01b031681565b3360009081526012602052604090205460ff161515600114612b735760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085206001600160a01b03909416855260019093019052912055565b601d5481565b601e5481565b612bb1611848565b6001600160a01b0316336001600160a01b031614612c005760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191660011790555182917f52ebf9d662e8bc70841a5b603c1711882a8e4b11a663af6b5709286fe7bd964591a250565b612c4b612668565b612c8a576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19166001179055517f6d3bdb877ca7bde5be7e4afec9b4afd12e4f3dd1188c8fa57a7802f0f6cfa4d49190a250565b612cde6124e6565b6001600160a01b0316336001600160a01b031614612d2d5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b60208181556040805183815290517faf1ea5ac33bf092763f62a127ef50006ae56eef9cc122568bea97c7308d17376929181900390910190a150565b6000546001600160a01b031681565b612d806124e6565b6001600160a01b0316336001600160a01b031614612dcf5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000908152601c60205260409020805460ff19166001179055565b60215481565b600d5481565b612dfe612668565b612e3d576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040517f0e6436d2b3e53a8a3ec2fbdd1d22525f0cd81d796bcb4beeef7337031a7e5efa90600090a250565b3360009081526012602052604090205460ff161515600114612eda5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b0316600090815260246020526040902080546001019055565b3360009081526012602052604090205460ff161515600114612f4d5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03891660009081526017602090815260408083208b845290915290208781556001810187905560028101869055600381018590556004810184905560058101839055600601819055612fad8989898989898989896124fb565b6001600160a01b038a1660009081526017602090815260408083208c845290915290206007015585151580612fe25750600085115b15612ff657612ff1888a613ded565b613000565b613000888a613e2d565b6001600160a01b03891660008181526017602090815260408083208c84528252918290206007015482518b81529182018a9052818301899052606082018890526080820187905260a0820186905260c0820185905291518b9392917f35ea872e77adbec19df83a66765d5bdc0adfe73d9ada9518cb384242ddb40d5d919081900360e00190a4505050505050505050565b3360009081526012602052604090205460ff1615156001146130e45760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156131265760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038316600090815260146020526040902054811115613193576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b0383166000908152601460205260409020546131bc908263ffffffff613dab16565b6001600160a01b0380851660009081526014602052604080822093909355908416815220546131f1908263ffffffff613c1a16565b6001600160a01b0380841660008181526014602052604080822094909455600c5484516323de665160e01b81528885166004820152602481019390935260448301869052935193909216926323de66519260648084019391929182900301818387803b15801561326057600080fd5b505af1158015613274573d6000803e3d6000fd5b50506040805184815290516001600160a01b038087169450871692507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a36001600160a01b0383166000908152601460205260409020546132de90849061257f565b6001600160a01b03841660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a36001600160a01b03821660009081526014602052604090205461335090839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a3505050565b6009546001600160a01b031681565b600054600160a01b900460ff1681565b6001600160a01b031660009081526023602052604090205490565b600a546001600160a01b031633146134265760405162461bcd60e51b815260040180806020018281038252603d8152602001806141ea603d913960400191505060405180910390fd5b6004819055613433613c7b565b6040805182815290517f38e3203d00fb51f959df7882c56c583370da2f7abea215c09e83e7ffa61281d29181900360200190a150565b613471612668565b6134b0576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600b80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f631bdf9495e4e83ab921eecb28e1057d3598a3fa0fc5f40b06bafe3e7333bc5c9181900360200190a150565b60205481565b6135126124e6565b6001600160a01b0316336001600160a01b0316146135615760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601e54613574908263ffffffff613c1a16565b601e819055601d5460408051928352602083019190915280517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a09281900390910190a150565b6135c2611848565b6001600160a01b0316336001600160a01b0316146136115760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff1916600190811790915560408051338152602081019290925280517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c29281900390910190a1565b60225460ff1681565b3360009081526012602052604090205460ff1615156001146136ba5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03808416600081815260156020908152604080832094871680845294825291829020859055815185815291517f3c07380f6fcae3bac39771c60e5c680334073911f2176b65f1d6925ba0badcdf9281900390910190a3505050565b613724611848565b6001600160a01b0316336001600160a01b0316146137735760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6305f5e10081116137b55760405162461bcd60e51b81526004018080602001828103825260278152602001806141076027913960400191505060405180910390fd5b60058190556040805182815290517f258a1584bca0aad852538c9d396233520174feedba906a03d19b307d3bad5f309181900360200190a150565b60006137fa612668565b613839576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6138506125c9565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156138a057600080fd5b505af11580156138b4573d6000803e3d6000fd5b505050506040513d60208110156138ca57600080fd5b50519392505050565b6138db6119aa565b6001600160a01b0316336001600160a01b03161461392a5760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040517f47c6cd80582c55aabfec5a8be39d30b380cf41ba92dd2d13ba626c48c96bf27690600090a250565b6001600160a01b03919091166000908152601760209081526040808320938352929052206003015490565b6009546001600160a01b031690565b600b546001600160a01b031681565b60105490565b6139cb611848565b6001600160a01b0316336001600160a01b031614613a1a5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6003819055613a27613c7b565b6040805182815290517ff915189a6212c055e85c9c0dc760b7a2a5d1ff9a9e64bd9af0a9897b4046dcd99181900360200190a150565b6001600160a01b03166000908152601b602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206001015490565b60009081526018602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206004015490565b613ae8612668565b613b27576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b613b3081613eb9565b50565b6008546001600160a01b031681565b6007546001600160a01b031681565b6001600160a01b03919091166000908152601760209081526040808320938352929052206005015490565b600f5481565b613b8a6124e6565b6001600160a01b0316336001600160a01b031614613bd95760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601f8190556040805182815290517f0969f79b044617688492c7c9b226129947037ca88c450002a7561ed78aa549ac9181900360200190a150565b60115490565b600082820183811015613c74576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b613ca4600454613c98600354600254613c1a90919063ffffffff16565b9063ffffffff613c1a16565b600181905560408051918252517f5b1767df4e2cc8a7b2716959e609e0cdd987c9b88ac27b7fc4be99435aa1673b9181900360200190a1565b600082613cec5750600061167a565b82820282848281613cf957fe5b0414613c745760405162461bcd60e51b81526004018080602001828103825260218152602001806141c96021913960400191505060405180910390fd5b6000613c7483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f59565b600e81905560405181907fb11f7283fda904f54a0fc8af727d3bf56e40a6cbf7c8fbb177083f0a335152ed90600090a250565b6000613c7483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613ffb565b6000613df98383612201565b9050806126e2576000613e106001613c9886613aa3565b9050613e1c8482611924565b613e27848483612679565b50505050565b6000613e398383612201565b90506000613e4684613aa3565b90506000613e5485836119cd565b90508215613eb25781831015613e7a57613e6f858285611857565b613e7a858285612b20565b613e8685600084611857565b613e9285856000612b20565b8115613eb257613eb285613ead84600163ffffffff613dab16565b611924565b5050505050565b6001600160a01b038116613efe5760405162461bcd60e51b81526004018080602001828103825260288152602001806141a16028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008183613fe55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613faa578181015183820152602001613f92565b50505050905090810190601f168015613fd75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613ff157fe5b0495945050505050565b6000818484111561404d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613faa578181015183820152602001613f92565b50505090039056fe4d6f727068657253746174653a2043616c6c6572206973206e6f7420746865204272696467652e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e7473206e65656420746f206265206c657373206f7220657175616c20746f2031353030302e4d6f727068657253746174653a204f6e6c7920506c6174666f726d20697320616c6c6f77656420746f2065786563757465206f7065726174696f6e2e4d6f727068657253746174653a204c6576657261676520707265636973696f6e206973203165384d6f727068657253746174653a2043616c6c696e6720636f6e7472616374206e6f742074686520476f7665726e616e636520436f6e74726163742e2041626f7274696e672e4d6f727068657253746174653a2043616e206f6e6c792062652063616c6c6564206f6e206d61696e636861696e2e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f727068657253746174653a2043616c6c6572206973206e6f74207468652053696465636861696e204f70657261746f722e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e74732063616e206f6e6c7920626520736574206f6e20457468657265756d2e4d6f727068657253746174653a2043616c6c6572206973206e6f74207468652041646d696e6973747261746f722e2041626f7274696e672e4d6f727068657253746174653a20436f6e7472616374207061757365642c2061626f7274696e674f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722ea265627a7a72315820160459360f99868cb32b4e506044eeea98d9c28ae8691a9461867be3f47ceaa764736f6c63430005100032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070dcdb66e128738189012dee12d7e13b377a1d3b000000000000000000000000e261d68bda5bd518598e31320ede6e1e2d53682f
-----Decoded View---------------
Arg [0] : _mainChain (bool): True
Arg [1] : _sideChainOperator (address): 0x70Dcdb66E128738189012dee12d7e13b377A1D3B
Arg [2] : _morpherTreasury (address): 0xE261D68bDa5BD518598E31320edE6E1E2d53682f
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [1] : 00000000000000000000000070dcdb66e128738189012dee12d7e13b377a1d3b
Arg [2] : 000000000000000000000000e261d68bda5bd518598e31320ede6e1e2d53682f
Deployed Bytecode Sourcemap
513:33429:10:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;513:33429:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23210:503;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23210:503:10;;:::i;:::-;;24288:185;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24288:185:10;;:::i;15142:125::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15142:125:10;-1:-1:-1;;;;;15142:125:10;;:::i;14275:175::-;;;:::i;:::-;;;;;;;;;;;;;;;;1156:32;;;:::i;:::-;;;;-1:-1:-1;;;;;1156:32:10;;;;;;;;;;;;;;16815:158;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16815:158:10;-1:-1:-1;;;;;16815:158:10;;:::i;20958:153::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;20958:153:10;;;;;;;;;;:::i;675:31::-;;;:::i;17843:128::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17843:128:10;-1:-1:-1;;;;;17843:128:10;;:::i;:::-;;;;;;;;;;;;;;;;;;26065:112;;;:::i;28242:666::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;28242:666:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21336:215;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21336:215:10;-1:-1:-1;;;;;21336:215:10;;:::i;17142:124::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17142:124:10;-1:-1:-1;;;;;17142:124:10;;:::i;25904:155::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25904:155:10;-1:-1:-1;;;;;25904:155:10;;:::i;22683:94::-;;;:::i;11643:176::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11643:176:10;;;-1:-1:-1;;;;;11643:176:10;;;;;;;;;;:::i;612:26::-;;;:::i;30154:171::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30154:171:10;;;;;;;;:::i;712:32::-;;;:::i;3682:35::-;;;:::i;11043:172::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11043:172:10;;;;;;;:::i;12254:148::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12254:148:10;-1:-1:-1;;;;;12254:148:10;;:::i;25771:127::-;;;:::i;21557:116::-;;;:::i;22400:93::-;;;:::i;10851:186::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10851:186:10;;;;;;;:::i;12045:203::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12045:203:10;;;;;;;;:::i;12760:146::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12760:146:10;-1:-1:-1;;;;;12760:146:10;;:::i;29803:171::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;29803:171:10;;;;;;;;:::i;750:38::-;;;:::i;18760:450::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;18760:450:10;;;;;;;;:::i;12408:346::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12408:346:10;;;;;;;;:::i;14746:170::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14746:170:10;;:::i;21946:176::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21946:176:10;-1:-1:-1;;;;;21946:176:10;;:::i;24479:125::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24479:125:10;;:::i;25488:277::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25488:277:10;;:::i;1516:52::-;;;:::i;14456:133::-;;;:::i;25146:125::-;;;:::i;15708:144::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15708:144:10;-1:-1:-1;;;;;15708:144:10;;:::i;981:26::-;;;:::i;23014:190::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23014:190:10;-1:-1:-1;;;;;23014:190:10;;:::i;16979:157::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16979:157:10;-1:-1:-1;;;;;16979:157:10;;:::i;644:25::-;;;:::i;30901:186::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30901:186:10;;;;;;;;:::i;10665:180::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10665:180:10;;;;;;-1:-1:-1;;;;;10665:180:10;;:::i;16219:226::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16219:226:10;;:::i;15423:157::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;15423:157:10;;;;;;;;:::i;33564:376::-;;;:::i;1228:27::-;;;:::i;20627:123::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20627:123:10;-1:-1:-1;;;;;20627:123:10;;:::i;1482:137:13:-;;;:::i;21830:110:10:-;;;:::i;16079:134::-;;;:::i;28914:710::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;28914:710:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;1376:47::-;;;:::i;24902:111::-;;;:::i;29630:167::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;29630:167:10;;;;;;;;:::i;4160:36::-;;;:::i;682:77:13:-;;;:::i;17684:153:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17684:153:10;-1:-1:-1;;;;;17684:153:10;;:::i;1038:90:13:-;;;:::i;11221:235:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11221:235:10;;;-1:-1:-1;;;;;11221:235:10;;;;;;;;;;:::i;1300:29::-;;;:::i;19216:532::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;19216:532:10;;;;;;;;:::i;15858:215::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15858:215:10;;:::i;13935:156::-;;;:::i;13335:433::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13335:433:10;;:::i;1014:32::-;;;:::i;11462:175::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11462:175:10;;;-1:-1:-1;;;;;11462:175:10;;;;;;;;;;:::i;3584:45::-;;;:::i;3635:41::-;;;:::i;24108:174::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24108:174:10;;:::i;17528:150::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17528:150:10;-1:-1:-1;;;;;17528:150:10;;:::i;14097:172::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14097:172:10;;:::i;262:21:13:-;;;:::i;14595:145:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14595:145:10;;:::i;3769:28::-;;;:::i;1262:32::-;;;:::i;22230:164::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22230:164:10;-1:-1:-1;;;;;22230:164:10;;:::i;15586:116::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15586:116:10;-1:-1:-1;;;;;15586:116:10;;:::i;26556:1680::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;26556:1680:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;18187:567::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;18187:567:10;;;;;;;;;;;;;;;;;:::i;1121:29::-;;;:::i;585:21::-;;;:::i;15273:144::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15273:144:10;-1:-1:-1;;;;;15273:144:10;;:::i;20386:235::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20386:235:10;;:::i;21679:145::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21679:145:10;-1:-1:-1;;;;;21679:145:10;;:::i;3723:40::-;;;:::i;13076:253::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13076:253:10;;:::i;25019:121::-;;;:::i;3803:32::-;;;:::i;20756:196::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;20756:196:10;;;;;;;;;;;;;;;;;:::i;24610:286::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24610:286:10;;:::i;2498:184:13:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;2498:184:13;;;;;;;;:::i;22499:178:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22499:178:10;-1:-1:-1;;;;;22499:178:10;;:::i;30331:180::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30331:180:10;;;;;;;;:::i;22128:96::-;;;:::i;1194:28::-;;;:::i;26183:153::-;;;:::i;20164:216::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20164:216:10;;:::i;12912:158::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12912:158:10;-1:-1:-1;;;;;12912:158:10;;:::i;29980:168::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;29980:168:10;;;;;;;;:::i;10499:160::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10499:160:10;;:::i;30517:183::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30517:183:10;;;;;;;;:::i;1790:107:13:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1790:107:13;-1:-1:-1;;;;;1790:107:13;;:::i;1087:28:10:-;;;:::i;1052:29::-;;;:::i;30706:189::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30706:189:10;;;;;;;;:::i;1336:34::-;;;:::i;13774:155::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13774:155:10;;:::i;16451:141::-;;;:::i;23210:503::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;23302:9:10;;-1:-1:-1;;;23302:9:10;;;;:17;;23315:4;23302:17;23298:291;;;23368:5;23343:21;:30;;23335:111;;;;-1:-1:-1;;;23335:111:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23298:291;;;23485:26;;23477:101;;;;-1:-1:-1;;;23477:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23598:17;:41;;;23668:14;;23654:52;;23618:21;;-1:-1:-1;;;;;23668:14:10;;23654:52;;23668:14;;23654:52;23210:503;:::o;24288:185::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24410:5;24376:31;;;:12;:31;;;;;;:39;;-1:-1:-1;;24376:39:10;;;24430:36;24389:17;;24430:36;;;24288:185;:::o;15142:125::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15219:26:10;;;;;:16;:26;;;;;15248:12;15219:41;;15142:125::o;14275:175::-;14328:14;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14354:13;:15;;;;;;;;14384:29;;;;;;;;;;;;;;;;-1:-1:-1;14430:13:10;;14275:175;:::o;1156:32::-;;;-1:-1:-1;;;;;1156:32:10;;:::o;16815:158::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;16881:21:10;;;;;;:11;:21;;;;;;:28;;-1:-1:-1;;16881:28:10;16905:4;16881:28;;;16924:42;16953:12;;16881:21;16924:42;;;16815:158;:::o;20958:153::-;-1:-1:-1;;;;;21075:20:10;;;21039:17;21075:20;;;:7;:20;;;;;;;;:29;;;;;;;;;;20958:153;;;;;:::o;675:31::-;;;;:::o;17843:128::-;-1:-1:-1;;;;;17939:25:10;17905:15;17939:25;;;:15;:25;;;;;;;;;17843:128::o;26065:112::-;26153:17;;-1:-1:-1;;;;;26153:17:10;26065:112;:::o;28242:666::-;-1:-1:-1;;;;;28572:19:10;;;;28352;28572;;;:9;:19;;;;;;;;:30;;;;;;;:41;;;;28623:42;;;;28675:45;;;;28730:46;;;;28786:48;;;;28844:47;;;;;28572:41;;28623:42;;28675:45;;28730:46;;28242:666::o;21336:215::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;21433:17:10;:49;;-1:-1:-1;;;;;;21433:49:10;;-1:-1:-1;;;;;21433:49:10;;;;;;;;;;;;21497:47;;;;-1:-1:-1;;21497:47:10;21336:215;:::o;17142:124::-;-1:-1:-1;;;;;17238:21:10;17204:15;17238:21;;;:11;:21;;;;;;;;;17142:124::o;25904:155::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;25979:17:10;:28;;-1:-1:-1;;;;;;25979:28:10;-1:-1:-1;;;;;25979:28:10;;;;;;;;26022:30;;;;-1:-1:-1;;26022:30:10;25904:155;:::o;22683:94::-;22757:13;;-1:-1:-1;;;;;22757:13:10;22683:94;:::o;11643:176::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11761:27;;;;:16;:27;;;;;;;;:40;;;:32;;;;:40;;;;;:51;;-1:-1:-1;;;;;;11761:51:10;-1:-1:-1;;;;;11761:51:10;;;;;;;;;11643:176::o;612:26::-;;;;:::o;30154:171::-;-1:-1:-1;;;;;30275:19:10;;;;30236:20;30275:19;;;:9;:19;;;;;;;;:30;;;;;;;:42;;;;30154:171::o;712:32::-;;;;:::o;3682:35::-;;;;:::o;11043:172::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11146:27;;;;:16;:27;;;;;;:62;11043:172::o;12254:148::-;-1:-1:-1;;;;;12362:33:10;12329:14;12362:33;;;:23;:33;;;;;;;12254:148::o;25771:127::-;25872:19;;25771:127;:::o;21557:116::-;21649:17;;;;;-1:-1:-1;;;;;21649:17:10;;21557:116::o;22400:93::-;22474:12;;-1:-1:-1;;;;;22474:12:10;22400:93;:::o;10851:186::-;10948:16;10983:27;;;:16;:27;;;;;;;;:47;;;:32;;;;:47;;;;;-1:-1:-1;;;;;10983:47:10;;10851:186::o;12045:203::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12143:33:10;;;;;;:23;:33;;;;;;;;;:42;;;12200:41;;;;;;;;;;;;;;;;;;;;;;12045:203;;:::o;12760:146::-;-1:-1:-1;;;;;12867:32:10;12834:14;12867:32;;;:22;:32;;;;;;;12760:146::o;29803:171::-;-1:-1:-1;;;;;29924:19:10;;;;29885:20;29924:19;;;:9;:19;;;;;;;;:30;;;;;;;:42;;29803:171::o;750:38::-;;;;:::o;18760:450::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7415:6;;;;:15;7407:67;;;;-1:-1:-1;;;7407:67:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18869:18:10;;;;;;:8;:18;;;;;;:30;;18892:6;18869:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;18848:18:10;;;;;;:8;:18;;;;;:51;18922:10;;:22;;18937:6;18922:22;:14;:22;:::i;:::-;18909:10;:35;18954:19;:17;:19::i;:::-;18997:12;;18983:70;;;-1:-1:-1;;;18983:70:10;;18997:12;18983:70;;;;;;-1:-1:-1;;;;;18983:70:10;;;;;;;;;;;;;;;18997:12;;;;;18983:40;;:70;;;;;;;;;;18997:12;;18983:70;;;5:2:-1;;;;30:1;27;20:12;5:2;18983:70:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;19091:10:10;;19068:34;;;;;;;;;;;;;;;-1:-1:-1;;;;;19068:34:10;;;-1:-1:-1;19068:34:10;;-1:-1:-1;19068:34:10;;;;;;;-1:-1:-1;;;;;19183:18:10;;;;;;:8;:18;;;;;;19158:44;;19173:8;;19158:14;:44::i;:::-;-1:-1:-1;;;;;19117:86:10;;19138:18;;;;:8;:18;;;;;;;;;;19117:86;;;;;;;;;;;;;;;;;18760:450;;:::o;12408:346::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12505:32:10;;;;;;:22;:32;;;;;;;;:41;;;12556:26;:36;;;;12595:3;12556:42;;12713:32;;12688:58;;12528:8;;12688:14;:58::i;:::-;-1:-1:-1;;;;;12654:32:10;;;;;;:22;:32;;;;;;;;;;12613:134;;;;;;;;;;;;;;;;;;;;;;;;;12408:346;;:::o;14746:170::-;14829:20;14868:41;;;:26;:41;;;;;;;;;14746:170::o;21946:176::-;7714:15;:13;:15::i;:::-;-1:-1:-1;;;;;7700:29:10;:10;-1:-1:-1;;;;;7700:29:10;;7692:111;;;;-1:-1:-1;;;7692:111:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22033:14;:35;;-1:-1:-1;;;;;;22033:35:10;-1:-1:-1;;;;;22033:35:10;;;;;;;;22083:32;;;;-1:-1:-1;;22083:32:10;21946:176;:::o;24479:125::-;24543:12;24574:23;;;:12;:23;;;;;;;;;24479:125::o;25488:277::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25578:19;:42;;;25665:3;25630:32;:38;25711:47;;25600:20;;25711:47;;-1:-1:-1;;25711:47:10;25488:277;:::o;1516:52::-;;;;:::o;14456:133::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14516:20;:28;;-1:-1:-1;;14516:28:10;;;14559:23;;;;14539:5;;14559:23;14456:133::o;25146:125::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25205:6;:14;;-1:-1:-1;;25205:14:10;;;25234:30;;;25246:10;25234:30;;25214:5;25234:30;;;;;;;;;;;;;;;;;25146:125::o;15708:144::-;-1:-1:-1;;;;;15819:26:10;15775:25;15819:26;;;:16;:26;;;;;;;15708:144::o;981:26::-;;;;;;:::o;23014:190::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;23095:14:10;:35;;-1:-1:-1;;;;;;23095:35:10;-1:-1:-1;;;;;23095:35:10;;;;;;;;23179:17;;23145:52;;23179:17;;23095:35;23145:52;;-1:-1:-1;;23145:52:10;23014:190;:::o;16979:157::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;17044:21:10;;17068:5;17044:21;;;:11;:21;;;;;;:29;;-1:-1:-1;;17044:29:10;;;17088:41;17116:12;;17044:21;17088:41;;;16979:157;:::o;644:25::-;;;;:::o;30901:186::-;-1:-1:-1;;;;;31032:19:10;;;;30988:25;31032:19;;;:9;:19;;;;;;;;:30;;;;;;;:47;;;;30901:186::o;10665:180::-;10755:21;10795:27;;;:16;:27;;;;;;;;-1:-1:-1;;;;;10795:43:10;;;;:33;;:43;;;;;;10665:180;;;;:::o;16219:226::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;16316:24:10;:52;;;16383:55;;16343:25;;16383:55;;;;;16219:226;:::o;15423:157::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15527:26:10;;;;;;;:16;:26;;;;;:46;15423:157::o;33564:376::-;8496:9;;-1:-1:-1;;;8496:9:10;;;;:17;;8509:4;8496:17;8488:76;;;;-1:-1:-1;;;8488:76:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33635:14;;:32;;969:6;33635:32;:18;:32;:::i;:::-;33629:3;:38;33625:309;;;33683:15;33701:49;890:5;33701:34;33717:17;;33701:11;;:15;;:34;;;;:::i;:::-;:38;:49;:38;:49;:::i;:::-;33683:67;;33764:51;33782:32;969:6;33782:14;;:18;;:32;;;;:::i;:::-;33764:17;:51::i;:::-;33834:14;;33829:29;;-1:-1:-1;;;;;33834:14:10;33850:7;33829:4;:29::i;:::-;33899:14;;33877:46;;;;;;;;-1:-1:-1;;;;;33899:14:10;;;;33877:46;;;;;;;;;33625:309;;33564:376::o;1228:27::-;;;-1:-1:-1;;;;;1228:27:10;;:::o;20627:123::-;-1:-1:-1;;;;;20722:21:10;20688:15;20722:21;;;:8;:21;;;;;;;20627:123::o;1482:137:13:-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;1580:1;1564:6;;1543:40;;-1:-1:-1;;;;;1564:6:13;;;;1543:40;;1580:1;;1543:40;1610:1;1593:19;;-1:-1:-1;;;;;;1593:19:13;;;1482:137::o;21830:110:10:-;21920:13;;-1:-1:-1;;;;;21920:13:10;21830:110;:::o;16079:134::-;16185:21;;16079:134;:::o;28914:710::-;29299:308;;;;;;;;-1:-1:-1;;29299:308:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;29299:308:10;;;;;;29276:341;;;;;;28914:710::o;1376:47::-;;;;:::o;24902:111::-;24991:15;;24902:111;:::o;29630:167::-;29753:36;;;;;;;;-1:-1:-1;;29753:36:10;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;29753:36:10;;;;;;29743:47;;;;;;29630:167::o;4160:36::-;;;;:::o;682:77:13:-;720:7;746:6;-1:-1:-1;;;;;746:6:13;682:77;:::o;17684:153:10:-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;17755:25:10;;17783:5;17755:25;;;:15;:25;;;;;;:33;;-1:-1:-1;;17755:33:10;;;17803:27;;;17783:5;17803:27;17684:153;:::o;1038:90:13:-;1078:4;1115:6;-1:-1:-1;;;;;1115:6:13;1101:10;:20;;1038:90::o;11221:235:10:-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11333:52;11357:9;11368:8;11378:6;11333:23;:52::i;:::-;11395:54;11421:9;11432:8;11442:6;11395:25;:54::i;:::-;11221:235;;;:::o;1300:29::-;;;;:::o;19216:532::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7415:6;;;;:15;7407:67;;;;-1:-1:-1;;;7407:67:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19312:18:10;;;;;;:8;:18;;;;;;:28;-1:-1:-1;19312:28:10;19304:72;;;;;-1:-1:-1;;;19304:72:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19407:18:10;;;;;;:8;:18;;;;;;:30;;19430:6;19407:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;19386:18:10;;;;;;:8;:18;;;;;:51;19460:10;;:22;;19475:6;19460:22;:14;:22;:::i;:::-;19447:10;:35;19492:19;:17;:19::i;:::-;19535:12;;19521:70;;;-1:-1:-1;;;19521:70:10;;-1:-1:-1;;;;;19521:70:10;;;;;;;19535:12;19521:70;;;;;;;;;;;;;;19535:12;;;19521:40;;:70;;;;;19535:12;;19521:70;;;;;;19535:12;;19521:70;;;5:2:-1;;;;30:1;27;20:12;5:2;19521:70:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;19629:10:10;;19606:34;;;;;;;;;;;;;;;-1:-1:-1;;;;;19606:34:10;;;-1:-1:-1;19606:34:10;;-1:-1:-1;19606:34:10;;;;;;;-1:-1:-1;;;;;19721:18:10;;;;;;:8;:18;;;;;;19696:44;;19711:8;;19696:14;:44::i;15858:215::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15954:21;:46;;;16015:51;;;;;;;;;;;;;;;;;15858:215;:::o;13935:156::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14035:1;14006:26;:30;;;14051:33;;;;14035:1;14051:33;13935:156::o;13335:433::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13449:7;13420:26;;:36;13416:196;;;13501:26;;:39;;13532:7;13501:39;:30;:39;:::i;:::-;13472:26;:68;13416:196;;;13600:1;13571:26;:30;13416:196;13654:3;13621:30;:36;;;13702:26;;13672:89;;;;;;;;;;;;;;;;;;;;;;;;;;13335:433;:::o;1014:32::-;;;;;;-1:-1:-1;;;;;1014:32:10;;:::o;11462:175::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11578:27;;;;:16;:27;;;;;;;;-1:-1:-1;;;;;11578:43:10;;;;;:33;;;;:43;;;;:52;11462:175::o;3584:45::-;;;;:::o;3635:41::-;;;;:::o;24108:174::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24192:29;;;;:12;:29;;;;;;:36;;-1:-1:-1;;24192:36:10;24224:4;24192:36;;;24243:32;24205:15;;24243:32;;;24108:174;:::o;17528:150::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;17598:25:10;;;;;;:15;:25;;;;;;:32;;-1:-1:-1;;17598:32:10;17626:4;17598:32;;;17645:26;;;17598:25;17645:26;17528:150;:::o;14097:172::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14177:16;:32;;;14224:38;;;;;;;;;;;;;;;;;;;14097:172;:::o;262:21:13:-;;;-1:-1:-1;;;;;262:21:13;;:::o;14595:145:10:-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14685:41;;;;:26;:41;;;;;:48;;-1:-1:-1;;14685:48:10;14729:4;14685:48;;;14595:145::o;3769:28::-;;;;:::o;1262:32::-;;;;:::o;22230:164::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;22310:12:10;:32;;-1:-1:-1;;;;;;22310:32:10;-1:-1:-1;;;;;22310:32:10;;;;;;;;22357:30;;;;-1:-1:-1;;22357:30:10;22230:164;:::o;15586:116::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15667:26:10;;;;;:16;:26;;;;;:28;;;;;;15586:116::o;26556:1680::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;26891:19:10;;;;;;:9;:19;;;;;;;;:30;;;;;;;;:55;;;26956:41;;;:55;;;27021:42;;;:57;;;27088:45;;;:63;;;27161:46;;;:65;;;27236:48;;;:69;;;27315:47;;:67;;;27438:267;26891:19;:30;:55;26956;27021:57;27088:63;27161:65;27236:69;27315:67;27438:15;:267::i;:::-;-1:-1:-1;;;;;27392:19:10;;;;;;:9;:19;;;;;;;;:30;;;;;;;;:43;;:313;27719:15;;;;:35;;;27753:1;27738:12;:16;27719:35;27715:180;;;27770:40;27790:9;27801:8;27770:19;:40::i;:::-;27715:180;;;27841:43;27864:9;27875:8;27841:22;:43::i;:::-;-1:-1:-1;;;;;27909:320:10;;27934:19;;;;:9;:19;;;;;;;;:30;;;;;;;;;:43;;;27909:320;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28013:9;;27909:320;27934:43;27909:320;;;;;;;;;;26556:1680;;;;;;;;;:::o;18187:567::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7415:6;;;;:15;7407:67;;;;-1:-1:-1;;;7407:67:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18297:15:10;;;;;;:8;:15;;;;;;:25;-1:-1:-1;18297:25:10;18289:69;;;;;-1:-1:-1;;;18289:69:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18386:15:10;;;;;;:8;:15;;;;;;:27;;18406:6;18386:27;:19;:27;:::i;:::-;-1:-1:-1;;;;;18368:15:10;;;;;;;:8;:15;;;;;;:45;;;;18439:13;;;;;;;:25;;18457:6;18439:25;:17;:25;:::i;:::-;-1:-1:-1;;;;;18423:13:10;;;;;;;:8;:13;;;;;;:41;;;;18488:12;;18474:60;;-1:-1:-1;;;18474:60:10;;;;;;;;;;;;;;;;;;;;;;;;18488:12;;;;;18474:40;;:60;;;;;18423:13;;18474:60;;;;;;18423:13;18488:12;18474:60;;;5:2:-1;;;;30:1;27;20:12;5:2;18474:60:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;18549:28:10;;;;;;;;-1:-1:-1;;;;;18549:28:10;;;;-1:-1:-1;18549:28:10;;;-1:-1:-1;18549:28:10;;;;;;;;;-1:-1:-1;;;;;18649:15:10;;;;;;:8;:15;;;;;;18627:38;;18642:5;;18627:14;:38::i;:::-;-1:-1:-1;;;;;18592:74:10;;18610:15;;;;:8;:15;;;;;;;;;;18592:74;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18732:13:10;;;;;;:8;:13;;;;;;18712:34;;18727:3;;18712:14;:34::i;:::-;-1:-1:-1;;;;;18681:66:10;;18697:13;;;;:8;:13;;;;;;;;;;18681:66;;;;;;;;;;;;;;;;;18187:567;;;:::o;1121:29::-;;;-1:-1:-1;;;;;1121:29:10;;:::o;585:21::-;;;-1:-1:-1;;;585:21:10;;;;;:::o;15273:144::-;-1:-1:-1;;;;;15384:26:10;15340:25;15384:26;;;:16;:26;;;;;;;15273:144::o;20386:235::-;8052:17;;-1:-1:-1;;;;;8052:17:10;8038:10;:31;8030:105;;;;-1:-1:-1;;;8030:105:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20486:17;:41;;;20537:19;:17;:19::i;:::-;20571:43;;;;;;;;;;;;;;;;;20386:235;:::o;21679:145::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;21752:13:10;:26;;-1:-1:-1;;;;;21752:26:10;;-1:-1:-1;;;;;;21752:26:10;;;;;;;;21793:24;;;;;;;;;;;;;;;;21679:145;:::o;3723:40::-;;;;:::o;13076:253::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13179:26;;:39;;13210:7;13179:39;:30;:39;:::i;:::-;13150:26;:68;;;13291:30;;13233:89;;;;;;;;;;;;;;;;;;;;;;;;;13076:253;:::o;25019:121::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25076:6;:13;;-1:-1:-1;;25076:13:10;25085:4;25076:13;;;;;;25104:29;;;25116:10;25104:29;;;;;;;;;;;;;;;;;;;;;25019:121::o;3803:32::-;;;;;;:::o;20756:196::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;20858:14:10;;;;;;;:7;:14;;;;;;;;:24;;;;;;;;;;;;;:34;;;20907:38;;;;;;;;;;;;;;;;;20756:196;;;:::o;24610:286::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;890:5;24710:19;:31;24702:83;;;;-1:-1:-1;;;24702:83:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24795:15;:37;;;24847:42;;;;;;;;;;;;;;;;;24610:286;:::o;2498:184:13:-;2595:13;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;2634:13;-1:-1:-1;;;;;2627:30:13;;2658:7;:5;:7::i;:::-;2667;2627:48;;;;;;;;;;;;;-1:-1:-1;;;;;2627:48:13;-1:-1:-1;;;;;2627:48:13;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2627:48:13;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2627:48:13;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2627:48:13;;2498:184;-1:-1:-1;;;2498:184:13:o;22499:178:10:-;7714:15;:13;:15::i;:::-;-1:-1:-1;;;;;7700:29:10;:10;-1:-1:-1;;;;;7700:29:10;;7692:111;;;;-1:-1:-1;;;7692:111:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22584:13;:33;;-1:-1:-1;;;;;;22584:33:10;-1:-1:-1;;;;;22584:33:10;;;;;;;;22632:38;;;;-1:-1:-1;;22632:38:10;22499:178;:::o;30331:180::-;-1:-1:-1;;;;;30458:19:10;;;;30416:23;30458:19;;;:9;:19;;;;;;;;:30;;;;;;;:45;;;;30331:180::o;22128:96::-;22203:14;;-1:-1:-1;;;;;22203:14:10;22128:96;:::o;1194:28::-;;;-1:-1:-1;;;;;1194:28:10;;:::o;26183:153::-;26297:32;;26183:153;:::o;20164:216::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20255:16;:36;;;20301:19;:17;:19::i;:::-;20335:38;;;;;;;;;;;;;;;;;20164:216;:::o;12912:158::-;-1:-1:-1;;;;;13027:36:10;12990:18;13027:36;;;:26;:36;;;;;;;12912:158::o;29980:168::-;-1:-1:-1;;;;;30099:19:10;;;;30061;30099;;;:9;:19;;;;;;;;:30;;;;;;;:41;;;;29980:168::o;10499:160::-;10566:24;10609:27;;;:16;:27;;;;;:43;;10499:160::o;30517:183::-;-1:-1:-1;;;;;30646:19:10;;;;30603:24;30646:19;;;:9;:19;;;;;;;;:30;;;;;;;:46;;;;30517:183::o;1790:107:13:-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;1862:28;1881:8;1862:18;:28::i;:::-;1790:107;:::o;1087:28:10:-;;;-1:-1:-1;;;;;1087:28:10;;:::o;1052:29::-;;;-1:-1:-1;;;;;1052:29:10;;:::o;30706:189::-;-1:-1:-1;;;;;30839:19:10;;;;30794:26;30839:19;;;:9;:19;;;;;;;;:30;;;;;;;:48;;;;30706:189::o;1336:34::-;;;;:::o;13774:155::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13850:20;:29;;;13894:28;;;;;;;;;;;;;;;;;13774:155;:::o;16451:141::-;16561:24;;16451:141;:::o;834:176:14:-;892:7;923:5;;;946:6;;;;938:46;;;;;-1:-1:-1;;;938:46:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;834:176;-1:-1:-1;;;834:176:14:o;19993:165:10:-;20054:55;20091:17;;20054:32;20069:16;;20054:10;;:14;;:32;;;;:::i;:::-;:36;:55;:36;:55;:::i;:::-;20040:11;:69;;;20124:27;;;;;;;;;;;;;;;;19993:165::o;2159:459:14:-;2217:7;2458:6;2454:45;;-1:-1:-1;2487:1:14;2480:8;;2454:45;2521:5;;;2525:1;2521;:5;:1;2544:5;;;;;:10;2536:56;;;;-1:-1:-1;;;2536:56:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3073:130;3131:7;3157:39;3161:1;3164;3157:39;;;;;;;;;;;;;;;;;:3;:39::i;23719:155:10:-;23789:14;:32;;;23836:31;;23806:15;;23836:31;;;;;23719:155;:::o;1274:134:14:-;1332:7;1358:43;1362:1;1365;1358:43;;;;;;;;;;;;;;;;;:3;:43::i;31372:455:10:-;31501:24;31528:42;31552:7;31561:8;31528:23;:42::i;:::-;31501:69;-1:-1:-1;31584:21:10;31580:241;;31621:24;31648:34;31680:1;31648:27;31667:7;31648:18;:27::i;:34::-;31621:61;;31696:45;31715:7;31724:16;31696:18;:45::i;:::-;31755:55;31774:7;31783:8;31793:16;31755:18;:55::i;:::-;31580:241;31372:455;;;:::o;31833:1321::-;31953:24;31980:42;32004:7;32013:8;31980:23;:42::i;:::-;31953:69;;32071:18;32092:27;32111:7;32092:18;:27::i;:::-;32071:48;;32129:20;32152:46;32178:7;32187:10;32152:25;:46::i;:::-;32129:69;-1:-1:-1;32330:20:10;;32326:822;;32558:10;32539:16;:29;32535:216;;;32588:66;32614:7;32623:12;32637:16;32588:25;:66::i;:::-;32672:64;32696:7;32705:12;32719:16;32672:23;:64::i;:::-;32850:58;32876:7;32893:1;32897:10;32850:25;:58::i;:::-;32922:45;32946:7;32955:8;32965:1;32922:23;:45::i;:::-;33043:14;;33039:99;;33077:46;33096:7;33105:17;:10;33120:1;33105:17;:14;:17;:::i;:::-;33077:18;:46::i;:::-;31833:1321;;;;;:::o;2041:227:13:-;-1:-1:-1;;;;;2114:22:13;;2106:75;;;;-1:-1:-1;;;2106:75:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2217:6;;;2196:38;;-1:-1:-1;;;;;2196:38:13;;;;2217:6;;;2196:38;;;2244:6;:17;;-1:-1:-1;;;;;;2244:17:13;-1:-1:-1;;;;;2244:17:13;;;;;;;;;;2041:227::o;3718:338:14:-;3804:7;3904:12;3897:5;3889:28;;;;-1:-1:-1;;;3889:28:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3927:9;3943:1;3939;:5;;;;;;;3718:338;-1:-1:-1;;;;;3718:338:14:o;1732:187::-;1818:7;1853:12;1845:6;;;;1837:29;;;;-1:-1:-1;;;1837:29:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;1837:29:14;-1:-1:-1;;;1888:5:14;;;1732:187::o
Swarm Source
bzzr://160459360f99868cb32b4e506044eeea98d9c28ae8691a9461867be3f47ceaa7
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.