Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xcac58806dadd0002b31cb07e9f4113dbd40db1356c43f044db8a0a6118ba4da1 | 0x60c06040 | 2241139 | 895 days 22 hrs ago | MUX Protocol: Deployer | IN | Create: Reader | 0 ETH | 0.09838747286 ETH |
[ Download CSV Export ]
Contract Name:
Reader
Compiler Version
v0.7.4+commit.3f05b770
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.7.4; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/utils/Address.sol"; import "../Type.sol"; import "../interface/ILiquidityPoolFull.sol"; import "../interface/IPoolCreatorFull.sol"; import "../interface/IOracle.sol"; import "../interface/ISymbolService.sol"; import "../interface/ISymbolService.sol"; import "../libraries/SafeMathExt.sol"; import "../libraries/Constant.sol"; interface IInverseStateService { function isInverse(address liquidityPool, uint256 perpetualIndex) external view returns (bool); } contract Reader { using SafeMathExt for uint256; using SafeMathExt for int256; using SignedSafeMathUpgradeable for int256; using Address for address; IInverseStateService public immutable inverseStateService; struct LiquidityPoolReaderResult { bool isRunning; bool isFastCreationEnabled; // check Getter.sol for detail address[7] addresses; int256[5] intNums; uint256[6] uintNums; PerpetualReaderResult[] perpetuals; bool isAMMMaintenanceSafe; } struct PerpetualReaderResult { PerpetualState state; address oracle; // check Getter.sol for detail int256[42] nums; uint256 symbol; // minimum number in the symbol service string underlyingAsset; bool isMarketClosed; bool isTerminated; int256 ammCashBalance; int256 ammPositionAmount; bool isInversePerpetual; } struct AccountReaderResult { int256 cash; int256 position; int256 availableMargin; int256 margin; int256 settleableMargin; bool isInitialMarginSafe; bool isMaintenanceMarginSafe; bool isMarginSafe; int256 targetLeverage; } struct AccountsResult { address account; int256 position; int256 margin; bool isSafe; int256 availableCash; } address public immutable poolCreator; constructor(address poolCreator_, address inverseStateService_) { require(poolCreator_.isContract(), "poolCreator must be contract"); require(inverseStateService_.isContract(), "inverseStateService must be contract"); poolCreator = poolCreator_; inverseStateService = IInverseStateService(inverseStateService_); } /** * @notice Get the storage of the account in the perpetual * @param liquidityPool The address of the liquidity pool * @param perpetualIndex The index of the perpetual in the liquidity pool * @param account The address of the account * Note: When account == liquidityPool, is*Safe are meanless. Do not forget to sum * poolCash and availableCash of all perpetuals in a liquidityPool when * calculating AMM margin * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return accountStorage The storage of the account in the perpetual */ function getAccountStorage( address liquidityPool, uint256 perpetualIndex, address account ) public returns (bool isSynced, AccountReaderResult memory accountStorage) { try ILiquidityPool(liquidityPool).forceToSyncState() { isSynced = true; } catch { isSynced = false; } (bool success, bytes memory data) = liquidityPool.call( abi.encodeWithSignature("getMarginAccount(uint256,address)", perpetualIndex, account) ); require(success, "fail to retrieve margin account"); accountStorage = _parseMarginAccount(data); } /** * @notice If amm is maintenance safe. Function setEmergencyState will revert only if amm is not maintenance margin safe. * * NOTE: this should NOT be called on chain. * @param liquidityPool The address of the liquidity pool. * @return bool True if amm is maintenance margin safe. */ function isAMMMaintenanceSafe(address liquidityPool) public returns (bool) { uint256[6] memory uintNums; address imp = getImplementation(liquidityPool); if (isV103(imp)) { (, , , , uintNums) = getLiquidityPoolInfoV103(liquidityPool); } else { (, , , , uintNums) = ILiquidityPoolFull(liquidityPool).getLiquidityPoolInfo(); } // perpetual count if (uintNums[1] == 0) { return true; } try ILiquidityPoolGovernance(liquidityPool).setEmergencyState( Constant.SET_ALL_PERPETUALS_TO_EMERGENCY_STATE ) { return false; } catch { return true; } } function _parseMarginAccount(bytes memory data) internal pure returns (AccountReaderResult memory accountStorage) { require(data.length % 0x20 == 0, "malformed input data"); assembly { let len := mload(data) let src := add(data, 0x20) let dst := accountStorage for { let end := add(src, len) } lt(src, end) { src := add(src, 0x20) dst := add(dst, 0x20) } { mstore(dst, mload(src)) } } } /** * @notice Get the pool margin of the liquidity pool * @param liquidityPool The address of the liquidity pool * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return poolMargin The pool margin of the liquidity pool */ function getPoolMargin(address liquidityPool) public returns ( bool isSynced, int256 poolMargin, bool isSafe ) { try ILiquidityPool(liquidityPool).forceToSyncState() { isSynced = true; } catch { isSynced = false; } (poolMargin, isSafe) = ILiquidityPoolFull(liquidityPool).getPoolMargin(); } /** * @notice Query the price, fees and cost when trade agaist amm. * The trading price is determined by the AMM based on the index price of the perpetual. * * Flags is a 32 bit uint value which indicates: (from highest bit) * - close only only close position during trading; * - market order do not check limit price during trading; * - stop loss only available in brokerTrade mode; * - take profit only available in brokerTrade mode; * For stop loss and take profit, see `validateTriggerPrice` in OrderModule.sol for details. * * @param perpetualIndex The index of the perpetual in liquidity pool. * @param trader The address of trader. * @param amount The amount of position to trader, positive for buying and negative for selling. The amount always use decimals 18. * @param referrer The address of referrer who will get rebate from the deal. * @param flags The flags of the trade. * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return tradePrice The average fill price. * @return totalFee The total fee collected from the trader after the trade. * @return cost Deposit or withdraw to let effective leverage == targetLeverage if flags contain USE_TARGET_LEVERAGE. > 0 if deposit, < 0 if withdraw. */ function queryTrade( address liquidityPool, uint256 perpetualIndex, address trader, int256 amount, address referrer, uint32 flags ) external returns ( bool isSynced, int256 tradePrice, int256 totalFee, int256 cost ) { try ILiquidityPool(liquidityPool).forceToSyncState() { isSynced = true; } catch { isSynced = false; } (tradePrice, totalFee, cost) = ILiquidityPoolFull(liquidityPool).queryTrade( perpetualIndex, trader, amount, referrer, flags ); } /** * @notice Get the status of the liquidity pool * * NOTE: this should NOT be called on chain. * @param liquidityPool The address of the liquidity pool * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return pool The status of the liquidity pool */ function getLiquidityPoolStorage(address liquidityPool) public returns (bool isSynced, LiquidityPoolReaderResult memory pool) { try ILiquidityPool(liquidityPool).forceToSyncState() { isSynced = true; } catch { isSynced = false; } // pool address imp = getImplementation(liquidityPool); if (isV103(imp)) { ( pool.isRunning, pool.isFastCreationEnabled, pool.addresses, pool.intNums, pool.uintNums ) = getLiquidityPoolInfoV103(liquidityPool); } else { ( pool.isRunning, pool.isFastCreationEnabled, pool.addresses, pool.intNums, pool.uintNums ) = ILiquidityPoolFull(liquidityPool).getLiquidityPoolInfo(); } // perpetual uint256 perpetualCount = pool.uintNums[1]; address symbolService = IPoolCreatorFull(pool.addresses[0]).getSymbolService(); pool.perpetuals = new PerpetualReaderResult[](perpetualCount); for (uint256 i = 0; i < perpetualCount; i++) { getPerpetual(pool.perpetuals[i], symbolService, liquidityPool, i); } // leave this dangerous line at the end pool.isAMMMaintenanceSafe = true; if (perpetualCount > 0) { try ILiquidityPoolGovernance(liquidityPool).setEmergencyState( Constant.SET_ALL_PERPETUALS_TO_EMERGENCY_STATE ) { pool.isAMMMaintenanceSafe = false; } catch {} } } function getPerpetual( PerpetualReaderResult memory perp, address symbolService, address liquidityPool, uint256 perpetualIndex ) private { // perpetual (perp.state, perp.oracle, perp.nums) = ILiquidityPoolFull(liquidityPool).getPerpetualInfo( perpetualIndex ); // read more from symbol service perp.symbol = getMinSymbol(symbolService, liquidityPool, perpetualIndex); // read more from oracle perp.underlyingAsset = IOracle(perp.oracle).underlyingAsset(); perp.isMarketClosed = IOracle(perp.oracle).isMarketClosed(); perp.isTerminated = IOracle(perp.oracle).isTerminated(); // read more from account (perp.ammCashBalance, perp.ammPositionAmount, , , , , , , ) = ILiquidityPoolFull( liquidityPool ).getMarginAccount(perpetualIndex, liquidityPool); // read more from inverse service perp.isInversePerpetual = inverseStateService.isInverse(liquidityPool, perpetualIndex); } function readIndexPrices(address[] memory oracles) public returns ( bool[] memory isSuccess, int256[] memory indexPrices, uint256[] memory timestamps ) { isSuccess = new bool[](oracles.length); indexPrices = new int256[](oracles.length); timestamps = new uint256[](oracles.length); for (uint256 i = 0; i < oracles.length; i++) { if (!oracles[i].isContract()) { continue; } try IOracle(oracles[i]).priceTWAPShort() returns ( int256 indexPrice, uint256 timestamp ) { isSuccess[i] = true; indexPrices[i] = indexPrice; timestamps[i] = timestamp; } catch {} } } function getMinSymbol( address symbolService, address liquidityPool, uint256 perpetualIndex ) private view returns (uint256) { uint256[] memory symbols; symbols = ISymbolService(symbolService).getSymbols(liquidityPool, perpetualIndex); uint256 symbolLength = symbols.length; require(symbolLength >= 1, "symbol not found"); uint256 minSymbol = type(uint256).max; for (uint256 i = 0; i < symbolLength; i++) { minSymbol = minSymbol.min(symbols[i]); } return minSymbol; } /** * @notice Get the info of active accounts in the perpetual whose index within range [begin, end). * @param liquidityPool The address of the liquidity pool * @param perpetualIndex The index of the perpetual in the liquidity pool. * @param begin The begin index of account to retrieve. * @param end The end index of account, exclusive. * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return result An array of active accounts' info. */ function getAccountsInfo( address liquidityPool, uint256 perpetualIndex, uint256 begin, uint256 end ) public returns (bool isSynced, AccountsResult[] memory result) { address[] memory accounts = ILiquidityPoolFull(liquidityPool).listActiveAccounts( perpetualIndex, begin, end ); return getAccountsInfoByAddress(liquidityPool, perpetualIndex, accounts); } /** * @notice Get the info of given accounts. * @param liquidityPool The address of the liquidity pool * @param perpetualIndex The index of the perpetual in the liquidity pool. * @param accounts Account addresses. * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return result An array of active accounts' info. */ function getAccountsInfoByAddress( address liquidityPool, uint256 perpetualIndex, address[] memory accounts ) public returns (bool isSynced, AccountsResult[] memory result) { try ILiquidityPool(liquidityPool).forceToSyncState() { isSynced = true; } catch { isSynced = false; } result = new AccountsResult[](accounts.length); int256[42] memory nums; (, , nums) = ILiquidityPoolFull(liquidityPool).getPerpetualInfo(perpetualIndex); int256 unitAccumulativeFunding = nums[4]; for (uint256 i = 0; i < accounts.length; i++) { int256 cash; int256 margin; int256 position; bool isMaintenanceMarginSafe; (cash, position, , margin, , , isMaintenanceMarginSafe, , ) = ILiquidityPoolFull( liquidityPool ).getMarginAccount(perpetualIndex, accounts[i]); result[i].account = accounts[i]; result[i].position = position; result[i].margin = margin; result[i].isSafe = isMaintenanceMarginSafe; result[i].availableCash = cash.sub(position.wmul(unitAccumulativeFunding)); } } /** * @notice Query cash to add / share to mint when adding liquidity to the liquidity pool. * Only one of cashToAdd or shareToMint may be non-zero. * * @param liquidityPool The address of the liquidity pool * @param cashToAdd The amount of cash to add, always use decimals 18. * @param shareToMint The amount of share token to mint, always use decimals 18. * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return cashToAddResult The amount of cash to add, always use decimals 18. Equal to cashToAdd if cashToAdd is non-zero. * @return shareToMintResult The amount of cash to add, always use decimals 18. Equal to shareToMint if shareToMint is non-zero. */ function queryAddLiquidity( address liquidityPool, int256 cashToAdd, int256 shareToMint ) public returns ( bool isSynced, int256 cashToAddResult, int256 shareToMintResult ) { try ILiquidityPool(liquidityPool).forceToSyncState() { isSynced = true; } catch { isSynced = false; } (cashToAddResult, shareToMintResult) = ILiquidityPoolFull(liquidityPool).queryAddLiquidity( cashToAdd, shareToMint ); } /** * @notice Query cash to return / share to redeem when removing liquidity from the liquidity pool. * Only one of shareToRemove or cashToReturn may be non-zero. * * @param liquidityPool The address of the liquidity pool * @param cashToReturn The amount of cash to return, always use decimals 18. * @param shareToRemove The amount of share token to redeem, always use decimals 18. * @return isSynced True if the funding state is synced to real-time data. False if * error happens (oracle error, zero price etc.). In this case, * trading, withdraw (if position != 0), addLiquidity, removeLiquidity * will fail * @return shareToRemoveResult The amount of share token to redeem, always use decimals 18. Equal to shareToRemove if shareToRemove is non-zero. * @return cashToReturnResult The amount of cash to return, always use decimals 18. Equal to cashToReturn if cashToReturn is non-zero. */ function queryRemoveLiquidity( address liquidityPool, int256 shareToRemove, int256 cashToReturn ) public returns ( bool isSynced, int256 shareToRemoveResult, int256 cashToReturnResult ) { try ILiquidityPool(liquidityPool).forceToSyncState() { isSynced = true; } catch { isSynced = false; } (shareToRemoveResult, cashToReturnResult) = ILiquidityPoolFull(liquidityPool) .queryRemoveLiquidity(shareToRemove, cashToReturn); } function getImplementation(address proxy) public view returns (address) { IProxyAdmin proxyAdmin = IPoolCreatorFull(poolCreator).upgradeAdmin(); return proxyAdmin.getProxyImplementation(proxy); } //////////////////////////////////////////////////////////////////////////////////// // back-compatible: <= v1.0.3 function isV103(address imp) private pure returns (bool) { if ( // arb1 imp == 0xEf5D601ea784ABd465c788C431d990b620e5Fee6 || // arb-rinkeby imp == 0x755C852d94ffa5E9B6bE974A5051d23d5bE27e4F ) { return true; } return false; } function getLiquidityPoolInfoV103(address liquidityPool) private view returns ( bool isRunning, bool isFastCreationEnabled, address[7] memory addresses, int256[5] memory intNums, uint256[6] memory uintNums ) { uint256[4] memory old; (isRunning, isFastCreationEnabled, addresses, intNums, old) = ILiquidityPool103( liquidityPool ).getLiquidityPoolInfo(); uintNums[0] = old[0]; uintNums[1] = old[1]; uintNums[2] = old[2]; uintNums[3] = old[3]; uintNums[4] = 0; // liquidityCap. 0 means ∞ uintNums[5] = 0; // shareTransferDelay. old perpetual does not lock share tokens } function getL1BlockNumber() public view returns (uint256) { return block.number; } } // back-compatible interface ILiquidityPool103 { function getLiquidityPoolInfo() external view returns ( bool isRunning, bool isFastCreationEnabled, address[7] memory addresses, int256[5] memory intNums, uint256[4] memory uintNums ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.7.4; import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol"; /** * @notice Perpetual state: * - INVALID: Uninitialized or not non-existent perpetual; * - INITIALIZING: Only when LiquidityPoolStorage.isRunning == false. Traders cannot perform operations; * - NORMAL: Full functional state. Traders is able to perform all operations; * - EMERGENCY: Perpetual is unsafe and only clear is available; * - CLEARED: All margin account is cleared. Trade could withdraw remaining margin balance. */ enum PerpetualState { INVALID, INITIALIZING, NORMAL, EMERGENCY, CLEARED } enum OrderType { LIMIT, MARKET, STOP } /** * @notice Data structure to store risk parameter value. */ struct Option { int256 value; int256 minValue; int256 maxValue; } /** * @notice Data structure to store oracle price data. */ struct OraclePriceData { int256 price; uint256 time; } /** * @notice Data structure to store user margin information. See MarginAccountModule.sol for details. */ struct MarginAccount { int256 cash; int256 position; int256 targetLeverage; } /** * @notice Data structure of an order object. */ struct Order { address trader; address broker; address relayer; address referrer; address liquidityPool; int256 minTradeAmount; int256 amount; int256 limitPrice; int256 triggerPrice; uint256 chainID; uint64 expiredAt; uint32 perpetualIndex; uint32 brokerFeeLimit; uint32 flags; uint32 salt; } /** * @notice Core data structure, a core . */ struct LiquidityPoolStorage { bool isRunning; bool isFastCreationEnabled; // addresses address creator; address operator; address transferringOperator; address governor; address shareToken; address accessController; bool reserved3; // isWrapped uint256 scaler; uint256 collateralDecimals; address collateralToken; // pool attributes int256 poolCash; uint256 fundingTime; uint256 reserved5; uint256 operatorExpiration; mapping(address => int256) reserved1; bytes32[] reserved2; // perpetuals uint256 perpetualCount; mapping(uint256 => PerpetualStorage) perpetuals; // insurance fund int256 insuranceFundCap; int256 insuranceFund; int256 donatedInsuranceFund; address reserved4; uint256 liquidityCap; uint256 shareTransferDelay; // reserved slot for future upgrade bytes32[14] reserved; } /** * @notice Core data structure, storing perpetual information. */ struct PerpetualStorage { uint256 id; PerpetualState state; address oracle; int256 totalCollateral; int256 openInterest; // prices OraclePriceData indexPriceData; OraclePriceData markPriceData; OraclePriceData settlementPriceData; // funding state int256 fundingRate; int256 unitAccumulativeFunding; // base parameters int256 initialMarginRate; int256 maintenanceMarginRate; int256 operatorFeeRate; int256 lpFeeRate; int256 referralRebateRate; int256 liquidationPenaltyRate; int256 keeperGasReward; int256 insuranceFundRate; int256 reserved1; int256 maxOpenInterestRate; // risk parameters Option halfSpread; Option openSlippageFactor; Option closeSlippageFactor; Option fundingRateLimit; Option fundingRateFactor; Option ammMaxLeverage; Option maxClosePriceDiscount; // users uint256 totalAccount; int256 totalMarginWithoutPosition; int256 totalMarginWithPosition; int256 redemptionRateWithoutPosition; int256 redemptionRateWithPosition; EnumerableSetUpgradeable.AddressSet activeAccounts; // insurance fund int256 reserved2; int256 reserved3; // accounts mapping(address => MarginAccount) marginAccounts; Option defaultTargetLeverage; // keeper address reserved4; EnumerableSetUpgradeable.AddressSet ammKeepers; EnumerableSetUpgradeable.AddressSet reserved5; Option baseFundingRate; // reserved slot for future upgrade bytes32[9] reserved; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; pragma experimental ABIEncoderV2; import "./IPerpetual.sol"; import "./ILiquidityPool.sol"; import "./ILiquidityPoolGetter.sol"; import "./ILiquidityPoolGovernance.sol"; interface ILiquidityPoolFull is IPerpetual, ILiquidityPool, ILiquidityPoolGetter, ILiquidityPoolGovernance {}
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; import "./IAccessControl.sol"; import "./IPoolCreator.sol"; import "./ITracer.sol"; import "./IVersionControl.sol"; import "./IVariables.sol"; import "./IKeeperWhitelist.sol"; interface IPoolCreatorFull is IPoolCreator, ITracer, IVersionControl, IVariables, IAccessControl, IKeeperWhitelist { /** * @notice Owner of version control. */ function owner() external view override(IVersionControl, IVariables) returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; interface IOracle { /** * @dev The market is closed if the market is not in its regular trading period. */ function isMarketClosed() external returns (bool); /** * @dev The oracle service was shutdown and never online again. */ function isTerminated() external returns (bool); /** * @dev Get collateral symbol. */ function collateral() external view returns (string memory); /** * @dev Get underlying asset symbol. */ function underlyingAsset() external view returns (string memory); /** * @dev Mark price. */ function priceTWAPLong() external returns (int256 newPrice, uint256 newTimestamp); /** * @dev Index price. */ function priceTWAPShort() external returns (int256 newPrice, uint256 newTimestamp); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; interface ISymbolService { function isWhitelistedFactory(address factory) external view returns (bool); function addWhitelistedFactory(address factory) external; function removeWhitelistedFactory(address factory) external; function getPerpetualUID(uint256 symbol) external view returns (address liquidityPool, uint256 perpetualIndex); function getSymbols(address liquidityPool, uint256 perpetualIndex) external view returns (uint256[] memory symbols); function allocateSymbol(address liquidityPool, uint256 perpetualIndex) external; function assignReservedSymbol( address liquidityPool, uint256 perpetualIndex, uint256 symbol ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.7.4; import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol"; import "./Constant.sol"; import "./Utils.sol"; enum Round { CEIL, FLOOR } library SafeMathExt { using SafeMathUpgradeable for uint256; using SignedSafeMathUpgradeable for int256; /* * @dev Always half up for uint256 */ function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x.mul(y).add(Constant.UNSIGNED_ONE / 2) / Constant.UNSIGNED_ONE; } /* * @dev Always half up for uint256 */ function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x.mul(Constant.UNSIGNED_ONE).add(y / 2).div(y); } /* * @dev Always half up for uint256 */ function wfrac( uint256 x, uint256 y, uint256 z ) internal pure returns (uint256 r) { r = x.mul(y).add(z / 2).div(z); } /* * @dev Always half up if no rounding parameter */ function wmul(int256 x, int256 y) internal pure returns (int256 z) { z = roundHalfUp(x.mul(y), Constant.SIGNED_ONE) / Constant.SIGNED_ONE; } /* * @dev Always half up if no rounding parameter */ function wdiv(int256 x, int256 y) internal pure returns (int256 z) { if (y < 0) { y = neg(y); x = neg(x); } z = roundHalfUp(x.mul(Constant.SIGNED_ONE), y).div(y); } /* * @dev Always half up if no rounding parameter */ function wfrac( int256 x, int256 y, int256 z ) internal pure returns (int256 r) { int256 t = x.mul(y); if (z < 0) { z = neg(z); t = neg(t); } r = roundHalfUp(t, z).div(z); } function wmul( int256 x, int256 y, Round round ) internal pure returns (int256 z) { z = div(x.mul(y), Constant.SIGNED_ONE, round); } function wdiv( int256 x, int256 y, Round round ) internal pure returns (int256 z) { z = div(x.mul(Constant.SIGNED_ONE), y, round); } function wfrac( int256 x, int256 y, int256 z, Round round ) internal pure returns (int256 r) { int256 t = x.mul(y); r = div(t, z, round); } function abs(int256 x) internal pure returns (int256) { return x >= 0 ? x : neg(x); } function neg(int256 a) internal pure returns (int256) { return SignedSafeMathUpgradeable.sub(int256(0), a); } /* * @dev ROUND_HALF_UP rule helper. * You have to call roundHalfUp(x, y) / y to finish the rounding operation. * 0.5 ≈ 1, 0.4 ≈ 0, -0.5 ≈ -1, -0.4 ≈ 0 */ function roundHalfUp(int256 x, int256 y) internal pure returns (int256) { require(y > 0, "roundHalfUp only supports y > 0"); if (x >= 0) { return x.add(y / 2); } return x.sub(y / 2); } /* * @dev Division, rounding ceil or rounding floor */ function div( int256 x, int256 y, Round round ) internal pure returns (int256 divResult) { require(y != 0, "division by zero"); divResult = x.div(y); if (x % y == 0) { return divResult; } bool isSameSign = Utils.hasTheSameSign(x, y); if (round == Round.CEIL && isSameSign) { divResult = divResult.add(1); } if (round == Round.FLOOR && !isSameSign) { divResult = divResult.sub(1); } } function max(int256 a, int256 b) internal pure returns (int256) { return a >= b ? a : b; } function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.7.4; library Constant { address internal constant INVALID_ADDRESS = address(0); int256 internal constant SIGNED_ONE = 10**18; uint256 internal constant UNSIGNED_ONE = 10**18; uint256 internal constant PRIVILEGE_DEPOSIT = 0x1; uint256 internal constant PRIVILEGE_WITHDRAW = 0x2; uint256 internal constant PRIVILEGE_TRADE = 0x4; uint256 internal constant PRIVILEGE_LIQUIDATE = 0x8; uint256 internal constant PRIVILEGE_GUARD = PRIVILEGE_DEPOSIT | PRIVILEGE_WITHDRAW | PRIVILEGE_TRADE | PRIVILEGE_LIQUIDATE; // max number of uint256 uint256 internal constant SET_ALL_PERPETUALS_TO_EMERGENCY_STATE = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSetUpgradeable { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; import "../Type.sol"; interface IPerpetual { /** * @notice Deposit collateral to the perpetual. * Can only called when the perpetual's state is "NORMAL". * This method will always increase `cash` amount in trader's margin account. * * @param perpetualIndex The index of the perpetual in the liquidity pool. * @param trader The address of the trader. * @param amount The amount of collateral to deposit. The amount always use decimals 18. */ function deposit( uint256 perpetualIndex, address trader, int256 amount ) external; /** * @notice Withdraw collateral from the trader's account of the perpetual. * After withdrawn, trader shall at least has maintenance margin left in account. * Can only called when the perpetual's state is "NORMAL". * Margin account must at least keep * The trader's cash will decrease in the perpetual. * Need to update the funding state and the oracle price of each perpetual before * and update the funding rate of each perpetual after * * @param perpetualIndex The index of the perpetual in the liquidity pool. * @param trader The address of the trader. * @param amount The amount of collateral to withdraw. The amount always use decimals 18. */ function withdraw( uint256 perpetualIndex, address trader, int256 amount ) external; /** * @notice If the state of the perpetual is "CLEARED", anyone authorized withdraw privilege by trader can settle * trader's account in the perpetual. Which means to calculate how much the collateral should be returned * to the trader, return it to trader's wallet and clear the trader's cash and position in the perpetual. * * @param perpetualIndex The index of the perpetual in the liquidity pool * @param trader The address of the trader. */ function settle(uint256 perpetualIndex, address trader) external; /** * @notice Clear the next active account of the perpetual which state is "EMERGENCY" and send gas reward of collateral * to sender. If all active accounts are cleared, the clear progress is done and the perpetual's state will * change to "CLEARED". Active means the trader's account is not empty in the perpetual. * Empty means cash and position are zero * * @param perpetualIndex The index of the perpetual in the liquidity pool. */ function clear(uint256 perpetualIndex) external; /** * @notice Trade with AMM in the perpetual, require sender is granted the trade privilege by the trader. * The trading price is determined by the AMM based on the index price of the perpetual. * Trader must be initial margin safe if opening position and margin safe if closing position * @param perpetualIndex The index of the perpetual in the liquidity pool * @param trader The address of trader * @param amount The position amount of the trade * @param limitPrice The worst price the trader accepts * @param deadline The deadline of the trade * @param referrer The referrer's address of the trade * @param flags The flags of the trade * @return int256 The update position amount of the trader after the trade */ function trade( uint256 perpetualIndex, address trader, int256 amount, int256 limitPrice, uint256 deadline, address referrer, uint32 flags ) external returns (int256); /** * @notice Trade with AMM by the order, initiated by the broker. * The trading price is determined by the AMM based on the index price of the perpetual. * Trader must be initial margin safe if opening position and margin safe if closing position * @param orderData The order data object * @param amount The position amount of the trade * @return int256 The update position amount of the trader after the trade */ function brokerTrade(bytes memory orderData, int256 amount) external returns (int256); /** * @notice Liquidate the trader if the trader's margin balance is lower than maintenance margin (unsafe). * Liquidate can be considered as a forced trading between AMM and unsafe margin account; * Based on current liquidity of AMM, it may take positions up to an amount equal to all the position * of the unsafe account. Besides the position, trader need to pay an extra penalty to AMM * for taking the unsafe assets. See TradeModule.sol for ehe strategy of penalty. * * The liquidate price will be determined by AMM. * Caller of this method can be anyone, then get a reward to make up for transaction gas fee. * * If a trader's margin balance is lower than 0 (bankrupt), insurance fund will be use to fill the loss * to make the total profit and loss balanced. (first the `insuranceFund` then the `donatedInsuranceFund`) * * If insurance funds are drained, the state of perpetual will turn to enter "EMERGENCY" than shutdown. * Can only liquidate when the perpetual's state is "NORMAL". * * @param perpetualIndex The index of the perpetual in liquidity pool * @param trader The address of trader to be liquidated. * @return liquidationAmount The amount of positions actually liquidated in the transaction. The amount always use decimals 18. */ function liquidateByAMM(uint256 perpetualIndex, address trader) external returns (int256 liquidationAmount); /** * @notice This method is generally consistent with `liquidateByAMM` function, but there some difference: * - The liquidation price is no longer determined by AMM, but the mark price; * - The penalty is taken by trader who takes position but AMM; * * @param perpetualIndex The index of the perpetual in liquidity pool. * @param liquidator The address of liquidator to receive the liquidated position. * @param trader The address of trader to be liquidated. * @param amount The amount of position to be taken from liquidated trader. The amount always use decimals 18. * @param limitPrice The worst price liquidator accepts. * @param deadline The deadline of transaction. * @return liquidationAmount The amount of positions actually liquidated in the transaction. */ function liquidateByTrader( uint256 perpetualIndex, address liquidator, address trader, int256 amount, int256 limitPrice, uint256 deadline ) external returns (int256 liquidationAmount); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; pragma experimental ABIEncoderV2; import "../Type.sol"; interface ILiquidityPool { /** * @notice Initialize the liquidity pool and set up its configuration. * * @param operator The operator's address of the liquidity pool. * @param collateral The collateral's address of the liquidity pool. * @param collateralDecimals The collateral's decimals of the liquidity pool. * @param governor The governor's address of the liquidity pool. * @param initData A bytes array contains data to initialize new created liquidity pool. */ function initialize( address operator, address collateral, uint256 collateralDecimals, address governor, bytes calldata initData ) external; /** * @dev Upgrade LiquidityPool. Call this function after initialize() * * @param nextAddresses Implementations except the 1st one of ChainedProxy */ function upgradeChainedProxy(address[] memory nextAddresses) external; /** * @notice If you want to get the real-time data, call this function first */ function forceToSyncState() external; /** * @notice Add liquidity to the liquidity pool. * Liquidity provider deposits collaterals then gets share tokens back. * The ratio of added cash to share token is determined by current liquidity. * Can only called when the pool is running. * * @param cashToAdd The amount of cash to add. always use decimals 18. */ function addLiquidity(int256 cashToAdd) external; /** * @notice Remove liquidity from the liquidity pool. * Liquidity providers redeems share token then gets collateral back. * The amount of collateral retrieved may differ from the amount when adding liquidity, * The index price, trading fee and positions holding by amm will affect the profitability of providers. * Can only called when the pool is running. * * @param shareToRemove The amount of share token to remove. The amount always use decimals 18. * @param cashToReturn The amount of cash(collateral) to return. The amount always use decimals 18. */ function removeLiquidity(int256 shareToRemove, int256 cashToReturn) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; pragma experimental ABIEncoderV2; import "../Type.sol"; interface ILiquidityPoolGetter { /** * @notice Get the info of the liquidity pool * @return isRunning True if the liquidity pool is running * @return isFastCreationEnabled True if the operator of the liquidity pool is allowed to create new perpetual * when the liquidity pool is running * @return addresses The related addresses of the liquidity pool * @return intNums Int type properties, see below for details. * @return uintNums Uint type properties, see below for details. */ function getLiquidityPoolInfo() external view returns ( bool isRunning, bool isFastCreationEnabled, // [0] creator, // [1] operator, // [2] transferringOperator, // [3] governor, // [4] shareToken, // [5] collateralToken, // [6] vault, address[7] memory addresses, // [0] vaultFeeRate, // [1] poolCash, // [2] insuranceFundCap, // [3] insuranceFund, // [4] donatedInsuranceFund, int256[5] memory intNums, // [0] collateralDecimals, // [1] perpetualCount, // [2] fundingTime, // [3] operatorExpiration, // [4] liquidityCap, // [5] shareTransferDelay, uint256[6] memory uintNums ); /** * @notice Get the info of the perpetual. Need to update the funding state and the oracle price * of each perpetual before and update the funding rate of each perpetual after * @param perpetualIndex The index of the perpetual in the liquidity pool * @return state The state of the perpetual * @return oracle The oracle's address of the perpetual * @return nums The related numbers of the perpetual */ function getPerpetualInfo(uint256 perpetualIndex) external view returns ( PerpetualState state, address oracle, // [0] totalCollateral // [1] markPrice, (return settlementPrice if it is in EMERGENCY state) // [2] indexPrice, // [3] fundingRate, // [4] unitAccumulativeFunding, // [5] initialMarginRate, // [6] maintenanceMarginRate, // [7] operatorFeeRate, // [8] lpFeeRate, // [9] referralRebateRate, // [10] liquidationPenaltyRate, // [11] keeperGasReward, // [12] insuranceFundRate, // [13-15] halfSpread value, min, max, // [16-18] openSlippageFactor value, min, max, // [19-21] closeSlippageFactor value, min, max, // [22-24] fundingRateLimit value, min, max, // [25-27] ammMaxLeverage value, min, max, // [28-30] maxClosePriceDiscount value, min, max, // [31] openInterest, // [32] maxOpenInterestRate, // [33-35] fundingRateFactor value, min, max, // [36-38] defaultTargetLeverage value, min, max, // [39-41] baseFundingRate value, min, max, int256[42] memory nums ); /** * @notice Get the account info of the trader. Need to update the funding state and the oracle price * of each perpetual before and update the funding rate of each perpetual after * @param perpetualIndex The index of the perpetual in the liquidity pool * @param trader The address of the trader * @return cash The cash(collateral) of the account * @return position The position of the account * @return availableMargin The available margin of the account * @return margin The margin of the account * @return settleableMargin The settleable margin of the account * @return isInitialMarginSafe True if the account is initial margin safe * @return isMaintenanceMarginSafe True if the account is maintenance margin safe * @return isMarginSafe True if the total value of margin account is beyond 0 * @return targetLeverage The target leverage for openning position. */ function getMarginAccount(uint256 perpetualIndex, address trader) external view returns ( int256 cash, int256 position, int256 availableMargin, int256 margin, int256 settleableMargin, bool isInitialMarginSafe, bool isMaintenanceMarginSafe, bool isMarginSafe, // bankrupt int256 targetLeverage ); /** * @notice Get the number of active accounts in the perpetual. * Active means the trader's account is not empty in the perpetual. * Empty means cash and position are zero * @param perpetualIndex The index of the perpetual in the liquidity pool * @return activeAccountCount The number of active accounts in the perpetual */ function getActiveAccountCount(uint256 perpetualIndex) external view returns (uint256); /** * @notice Get the active accounts in the perpetual whose index between begin and end. * Active means the trader's account is not empty in the perpetual. * Empty means cash and position are zero * @param perpetualIndex The index of the perpetual in the liquidity pool * @param begin The begin index * @param end The end index * @return result The active accounts in the perpetual whose index between begin and end */ function listActiveAccounts( uint256 perpetualIndex, uint256 begin, uint256 end ) external view returns (address[] memory result); /** * @notice Get the progress of clearing active accounts. * Return the number of total active accounts and the number of active accounts not cleared * @param perpetualIndex The index of the perpetual in the liquidity pool * @return left The left active accounts * @return total The total active accounts */ function getClearProgress(uint256 perpetualIndex) external view returns (uint256 left, uint256 total); /** * @notice Get the pool margin of the liquidity pool. * Pool margin is how much collateral of the pool considering the AMM's positions of perpetuals * @return poolMargin The pool margin of the liquidity pool */ function getPoolMargin() external view returns (int256 poolMargin, bool isSafe); /** * @notice Query the price, fees and cost when trade agaist amm. * The trading price is determined by the AMM based on the index price of the perpetual. * This method should returns the same result as a 'read-only' trade. * WARN: the result of this function is base on current storage of liquidityPool, not the latest. * To get the latest status, call `syncState` first. * * Flags is a 32 bit uint value which indicates: (from highest bit) * - close only only close position during trading; * - market order do not check limit price during trading; * - stop loss only available in brokerTrade mode; * - take profit only available in brokerTrade mode; * For stop loss and take profit, see `validateTriggerPrice` in OrderModule.sol for details. * * @param perpetualIndex The index of the perpetual in liquidity pool. * @param trader The address of trader. * @param amount The amount of position to trader, positive for buying and negative for selling. The amount always use decimals 18. * @param referrer The address of referrer who will get rebate from the deal. * @param flags The flags of the trade. * @return tradePrice The average fill price. * @return totalFee The total fee collected from the trader after the trade. * @return cost Deposit or withdraw to let effective leverage == targetLeverage if flags contain USE_TARGET_LEVERAGE. > 0 if deposit, < 0 if withdraw. */ function queryTrade( uint256 perpetualIndex, address trader, int256 amount, address referrer, uint32 flags ) external returns ( int256 tradePrice, int256 totalFee, int256 cost ); /** * @notice Query cash to add / share to mint when adding liquidity to the liquidity pool. * Only one of cashToAdd or shareToMint may be non-zero. * * @param cashToAdd The amount of cash to add, always use decimals 18. * @param shareToMint The amount of share token to mint, always use decimals 18. * @return cashToAddResult The amount of cash to add, always use decimals 18. Equal to cashToAdd if cashToAdd is non-zero. * @return shareToMintResult The amount of cash to add, always use decimals 18. Equal to shareToMint if shareToMint is non-zero. */ function queryAddLiquidity(int256 cashToAdd, int256 shareToMint) external view returns (int256 cashToAddResult, int256 shareToMintResult); /** * @notice Query cash to return / share to redeem when removing liquidity from the liquidity pool. * Only one of shareToRemove or cashToReturn may be non-zero. * Can only called when the pool is running. * * @param shareToRemove The amount of share token to redeem, always use decimals 18. * @param cashToReturn The amount of cash to return, always use decimals 18. * @return shareToRemoveResult The amount of share token to redeem, always use decimals 18. Equal to shareToRemove if shareToRemove is non-zero. * @return cashToReturnResult The amount of cash to return, always use decimals 18. Equal to cashToReturn if cashToReturn is non-zero. */ function queryRemoveLiquidity(int256 shareToRemove, int256 cashToReturn) external view returns (int256 shareToRemoveResult, int256 cashToReturnResult); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; interface ILiquidityPoolGovernance { function setEmergencyState(uint256 perpetualIndex) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; interface IAccessControl { function grantPrivilege(address trader, uint256 privilege) external; function revokePrivilege(address trader, uint256 privilege) external; function isGranted( address owner, address trader, uint256 privilege ) external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; import "./IProxyAdmin.sol"; interface IPoolCreator { function upgradeAdmin() external view returns (IProxyAdmin proxyAdmin); /** * @notice Create a liquidity pool with the latest version. * The sender will be the operator of pool. * * @param collateral he collateral address of the liquidity pool. * @param collateralDecimals The collateral's decimals of the liquidity pool. * @param nonce A random nonce to calculate the address of deployed contracts. * @param initData A bytes array contains data to initialize new created liquidity pool. * @return liquidityPool The address of the created liquidity pool. */ function createLiquidityPool( address collateral, uint256 collateralDecimals, int256 nonce, bytes calldata initData ) external returns (address liquidityPool, address governor); /** * @notice Upgrade a liquidity pool and governor pair then call a patch function on the upgraded contract (optional). * This method checks the sender and forwards the request to ProxyAdmin to do upgrading. * * @param targetVersionKey The key of version to be upgrade up. The target version must be compatible with * current version. * @param dataForLiquidityPool The patch calldata for upgraded liquidity pool. * @param dataForGovernor The patch calldata of upgraded governor. */ function upgradeToAndCall( bytes32 targetVersionKey, bytes memory dataForLiquidityPool, bytes memory dataForGovernor ) external; /** * @notice Indicates the universe settle state. * If the flag set to true: * - all the pereptual created by this poolCreator can be settled immediately; * - all the trading method will be unavailable. */ function isUniverseSettled() external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; import "./IProxyAdmin.sol"; interface ITracer { /** * @notice Activate the perpetual for the trader. Active means the trader's account is not empty in * the perpetual. Empty means cash and position are zero. Can only called by a liquidity pool. * * @param trader The address of the trader. * @param perpetualIndex The index of the perpetual in the liquidity pool. * @return True if the activation is successful. */ function activatePerpetualFor(address trader, uint256 perpetualIndex) external returns (bool); /** * @notice Deactivate the perpetual for the trader. Active means the trader's account is not empty in * the perpetual. Empty means cash and position are zero. Can only called by a liquidity pool. * * @param trader The address of the trader. * @param perpetualIndex The index of the perpetual in the liquidity pool. * @return True if the deactivation is successful. */ function deactivatePerpetualFor(address trader, uint256 perpetualIndex) external returns (bool); /** * @notice Liquidity pool must call this method when changing its ownership to the new operator. * Can only be called by a liquidity pool. This method does not affect 'ownership' or privileges * of operator but only make a record for further query. * * @param liquidityPool The address of the liquidity pool. * @param operator The address of the new operator, must be different from the old operator. */ function registerOperatorOfLiquidityPool(address liquidityPool, address operator) external; /** * @notice Check if the liquidity pool exists. * * @param liquidityPool The address of the liquidity pool. * @return True if the liquidity pool exists. */ function isLiquidityPool(address liquidityPool) external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; import "./IProxyAdmin.sol"; interface IVersionControl { function owner() external view returns (address); function getLatestVersion() external view returns (bytes32 latestVersionKey); /** * @notice Get the details of the version. * * @param versionKey The key of the version to get. * @return liquidityPoolTemplate The address of the liquidity pool template. * @return governorTemplate The address of the governor template. * @return compatibility The compatibility of the specified version. */ function getVersion(bytes32 versionKey) external view returns ( address[] memory liquidityPoolTemplate, address governorTemplate, uint256 compatibility ); /** * @notice Get the description of the implementation of liquidity pool. * Description contains creator, create time, compatibility and note * * @param liquidityPool The address of the liquidity pool. * @param governor The address of the governor. * @return appliedVersionKey The version key of given liquidity pool and governor. */ function getAppliedVersionKey(address liquidityPool, address governor) external view returns (bytes32 appliedVersionKey); /** * @notice Check if a key is valid (exists). * * @param versionKey The key of the version to test. * @return isValid Return true if the version of given key is valid. */ function isVersionKeyValid(bytes32 versionKey) external view returns (bool isValid); /** * @notice Check if the implementation of liquidity pool target is compatible with the implementation base. * Being compatible means having larger compatibility. * * @param targetVersionKey The key of the version to be upgraded to. * @param baseVersionKey The key of the version to be upgraded from. * @return isCompatible True if the target version is compatible with the base version. */ function isVersionCompatible(bytes32 targetVersionKey, bytes32 baseVersionKey) external view returns (bool isCompatible); /** * @dev Get a certain number of implementations of liquidity pool within range [begin, end). * * @param begin The index of first element to retrieve. * @param end The end index of element, exclusive. * @return versionKeys An array contains current version keys. */ function listAvailableVersions(uint256 begin, uint256 end) external view returns (bytes32[] memory versionKeys); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; import "./IProxyAdmin.sol"; interface IVariables { function owner() external view returns (address); /** * @notice Get the address of the vault * @return address The address of the vault */ function getVault() external view returns (address); /** * @notice Get the vault fee rate * @return int256 The vault fee rate */ function getVaultFeeRate() external view returns (int256); /** * @notice Get the address of the access controller. It's always its own address. * * @return address The address of the access controller. */ function getAccessController() external view returns (address); /** * @notice Get the address of the symbol service. * * @return Address The address of the symbol service. */ function getSymbolService() external view returns (address); /** * @notice Set the vault address. Can only called by owner. * * @param newVault The new value of the vault fee rate */ function setVault(address newVault) external; /** * @notice Get the address of the mcb token. * @dev [ConfirmBeforeDeployment] * * @return Address The address of the mcb token. */ function getMCBToken() external pure returns (address); /** * @notice Set the vault fee rate. Can only called by owner. * * @param newVaultFeeRate The new value of the vault fee rate */ function setVaultFeeRate(int256 newVaultFeeRate) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; interface IKeeperWhitelist { /** * @notice Add an address to keeper whitelist. */ function addKeeper(address keeper) external; /** * @notice Remove an address from keeper whitelist. */ function removeKeeper(address keeper) external; /** * @notice Check if an address is in keeper whitelist. */ function isKeeper(address keeper) external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.7.4; interface IProxyAdmin { function getProxyImplementation(address proxy) external view returns (address); /** * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgrade(address proxy, address implementation) external; /** * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See * {TransparentUpgradeableProxy-upgradeToAndCall}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgradeAndCall( address proxy, address implementation, bytes memory data ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @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 SafeMathUpgradeable { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { 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) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { 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, reverting 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) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @title SignedSafeMath * @dev Signed math operations with safety checks that revert on error. */ library SignedSafeMathUpgradeable { int256 constant private _INT256_MIN = -2**255; /** * @dev Returns the multiplication of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { // 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; } require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow"); int256 c = a * b; require(c / a == b, "SignedSafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two signed 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(int256 a, int256 b) internal pure returns (int256) { require(b != 0, "SignedSafeMath: division by zero"); require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow"); int256 c = a / b; return c; } /** * @dev Returns the subtraction of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow"); return c; } /** * @dev Returns the addition of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow"); return c; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.7.4; import "@openzeppelin/contracts/utils/EnumerableSet.sol"; import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import "./SafeMathExt.sol"; library Utils { using SafeMathExt for int256; using SafeMathExt for uint256; using SafeMathUpgradeable for uint256; using SignedSafeMathUpgradeable for int256; using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set; /* * @dev Check if two numbers have the same sign. Zero has the same sign with any number */ function hasTheSameSign(int256 x, int256 y) internal pure returns (bool) { if (x == 0 || y == 0) { return true; } return (x ^ y) >> 255 == 0; } /** * @dev Check if the trader has opened position in the trade. * Example: 2, 1 => true; 2, -1 => false; -2, -3 => true * @param amount The position of the trader after the trade * @param delta The update position amount of the trader after the trade * @return True if the trader has opened position in the trade */ function hasOpenedPosition(int256 amount, int256 delta) internal pure returns (bool) { if (amount == 0) { return false; } return Utils.hasTheSameSign(amount, delta); } /* * @dev Split the delta to two numbers. * Use for splitting the trading amount to the amount to close position and the amount to open position. * Examples: 2, 1 => 0, 1; 2, -1 => -1, 0; 2, -3 => -2, -1 */ function splitAmount(int256 amount, int256 delta) internal pure returns (int256, int256) { if (Utils.hasTheSameSign(amount, delta)) { return (0, delta); } else if (amount.abs() >= delta.abs()) { return (delta, 0); } else { return (amount.neg(), amount.add(delta)); } } /* * @dev Check if amount will be away from zero or cross zero if added the delta. * Use for checking if trading amount will make trader open position. * Example: 2, 1 => true; 2, -1 => false; 2, -3 => true */ function isOpen(int256 amount, int256 delta) internal pure returns (bool) { return Utils.hasTheSameSign(amount, delta) || amount.abs() < delta.abs(); } /* * @dev Get the id of the current chain */ function chainID() internal pure returns (uint256 id) { assembly { id := chainid() } } // function toArray( // EnumerableSet.AddressSet storage set, // uint256 begin, // uint256 end // ) internal view returns (address[] memory result) { // require(end > begin, "begin should be lower than end"); // uint256 length = set.length(); // if (begin >= length) { // return result; // } // uint256 safeEnd = end.min(length); // result = new address[](safeEnd.sub(begin)); // for (uint256 i = begin; i < safeEnd; i++) { // result[i.sub(begin)] = set.at(i); // } // return result; // } function toArray( EnumerableSetUpgradeable.AddressSet storage set, uint256 begin, uint256 end ) internal view returns (address[] memory result) { require(end > begin, "begin should be lower than end"); uint256 length = set.length(); if (begin >= length) { return result; } uint256 safeEnd = end.min(length); result = new address[](safeEnd.sub(begin)); for (uint256 i = begin; i < safeEnd; i++) { result[i.sub(begin)] = set.at(i); } return result; } function toArray( EnumerableSetUpgradeable.Bytes32Set storage set, uint256 begin, uint256 end ) internal view returns (bytes32[] memory result) { require(end > begin, "begin should be lower than end"); uint256 length = set.length(); if (begin >= length) { return result; } uint256 safeEnd = end.min(length); result = new bytes32[](safeEnd.sub(begin)); for (uint256 i = begin; i < safeEnd; i++) { result[i.sub(begin)] = set.at(i); } return result; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"poolCreator_","type":"address"},{"internalType":"address","name":"inverseStateService_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"uint256","name":"perpetualIndex","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"getAccountStorage","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"components":[{"internalType":"int256","name":"cash","type":"int256"},{"internalType":"int256","name":"position","type":"int256"},{"internalType":"int256","name":"availableMargin","type":"int256"},{"internalType":"int256","name":"margin","type":"int256"},{"internalType":"int256","name":"settleableMargin","type":"int256"},{"internalType":"bool","name":"isInitialMarginSafe","type":"bool"},{"internalType":"bool","name":"isMaintenanceMarginSafe","type":"bool"},{"internalType":"bool","name":"isMarginSafe","type":"bool"},{"internalType":"int256","name":"targetLeverage","type":"int256"}],"internalType":"struct Reader.AccountReaderResult","name":"accountStorage","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"uint256","name":"perpetualIndex","type":"uint256"},{"internalType":"uint256","name":"begin","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"getAccountsInfo","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"int256","name":"position","type":"int256"},{"internalType":"int256","name":"margin","type":"int256"},{"internalType":"bool","name":"isSafe","type":"bool"},{"internalType":"int256","name":"availableCash","type":"int256"}],"internalType":"struct Reader.AccountsResult[]","name":"result","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"uint256","name":"perpetualIndex","type":"uint256"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"getAccountsInfoByAddress","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"int256","name":"position","type":"int256"},{"internalType":"int256","name":"margin","type":"int256"},{"internalType":"bool","name":"isSafe","type":"bool"},{"internalType":"int256","name":"availableCash","type":"int256"}],"internalType":"struct Reader.AccountsResult[]","name":"result","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"proxy","type":"address"}],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getL1BlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"}],"name":"getLiquidityPoolStorage","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"components":[{"internalType":"bool","name":"isRunning","type":"bool"},{"internalType":"bool","name":"isFastCreationEnabled","type":"bool"},{"internalType":"address[7]","name":"addresses","type":"address[7]"},{"internalType":"int256[5]","name":"intNums","type":"int256[5]"},{"internalType":"uint256[6]","name":"uintNums","type":"uint256[6]"},{"components":[{"internalType":"enum PerpetualState","name":"state","type":"uint8"},{"internalType":"address","name":"oracle","type":"address"},{"internalType":"int256[42]","name":"nums","type":"int256[42]"},{"internalType":"uint256","name":"symbol","type":"uint256"},{"internalType":"string","name":"underlyingAsset","type":"string"},{"internalType":"bool","name":"isMarketClosed","type":"bool"},{"internalType":"bool","name":"isTerminated","type":"bool"},{"internalType":"int256","name":"ammCashBalance","type":"int256"},{"internalType":"int256","name":"ammPositionAmount","type":"int256"},{"internalType":"bool","name":"isInversePerpetual","type":"bool"}],"internalType":"struct Reader.PerpetualReaderResult[]","name":"perpetuals","type":"tuple[]"},{"internalType":"bool","name":"isAMMMaintenanceSafe","type":"bool"}],"internalType":"struct Reader.LiquidityPoolReaderResult","name":"pool","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"}],"name":"getPoolMargin","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"internalType":"int256","name":"poolMargin","type":"int256"},{"internalType":"bool","name":"isSafe","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inverseStateService","outputs":[{"internalType":"contract IInverseStateService","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"}],"name":"isAMMMaintenanceSafe","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolCreator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"int256","name":"cashToAdd","type":"int256"},{"internalType":"int256","name":"shareToMint","type":"int256"}],"name":"queryAddLiquidity","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"internalType":"int256","name":"cashToAddResult","type":"int256"},{"internalType":"int256","name":"shareToMintResult","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"int256","name":"shareToRemove","type":"int256"},{"internalType":"int256","name":"cashToReturn","type":"int256"}],"name":"queryRemoveLiquidity","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"internalType":"int256","name":"shareToRemoveResult","type":"int256"},{"internalType":"int256","name":"cashToReturnResult","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"uint256","name":"perpetualIndex","type":"uint256"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"int256","name":"amount","type":"int256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint32","name":"flags","type":"uint32"}],"name":"queryTrade","outputs":[{"internalType":"bool","name":"isSynced","type":"bool"},{"internalType":"int256","name":"tradePrice","type":"int256"},{"internalType":"int256","name":"totalFee","type":"int256"},{"internalType":"int256","name":"cost","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"oracles","type":"address[]"}],"name":"readIndexPrices","outputs":[{"internalType":"bool[]","name":"isSuccess","type":"bool[]"},{"internalType":"int256[]","name":"indexPrices","type":"int256[]"},{"internalType":"uint256[]","name":"timestamps","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162002e1638038062002e168339810160408190526200003491620000fa565b62000053826001600160a01b0316620000d860201b620012a21760201c565b6200007b5760405162461bcd60e51b8152600401620000729062000131565b60405180910390fd5b6200009a816001600160a01b0316620000d860201b620012a21760201c565b620000b95760405162461bcd60e51b8152600401620000729062000168565b6001600160601b0319606092831b811660a052911b16608052620001ac565b803b15155b919050565b80516001600160a01b0381168114620000dd57600080fd5b600080604083850312156200010d578182fd5b6200011883620000e2565b91506200012860208401620000e2565b90509250929050565b6020808252601c908201527f706f6f6c43726561746f72206d75737420626520636f6e747261637400000000604082015260600190565b60208082526024908201527f696e7665727365537461746553657276696365206d75737420626520636f6e746040820152631c9858dd60e21b606082015260800190565b60805160601c60a05160601c612c36620001e06000398061038b528061112b5250806104bd52806117005250612c366000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806377ee51ee1161008c578063b9b3efe911610066578063b9b3efe91461021e578063bc0a260314610233578063c6c1decd14610246578063eb16510d1461024e576100ea565b806377ee51ee146101c85780637e4b4e45146101e9578063a90dc662146101fc576100ea565b80633c070544116100c85780633c0705441461014357806341de031a1461016557806346a83af814610187578063574408c1146101a7576100ea565b806304a6c736146100ef57806315ac72ca1461011b57806334a3cf331461013b575b600080fd5b6101026100fd366004611f2f565b61026f565b60405161011294939291906128cb565b60405180910390f35b61012e610129366004611e82565b610386565b604051610112919061274f565b61012e6104bb565b610156610151366004611eba565b6104df565b604051610112939291906128b3565b610178610173366004611e82565b6105e7565b60405161011293929190612899565b61019a610195366004611e82565b6106c4565b604051610112919061280b565b6101ba6101b5366004611e82565b6107fe565b604051610112929190612964565b6101db6101d6366004611ffd565b610ae8565b604051610112929190612816565b6101566101f7366004611eba565b610b8c565b61020f61020a366004612037565b610c36565b6040516101129392919061277c565b610226610e2f565b6040516101129190612aa4565b6101db610241366004611fa6565b610e33565b61012e611129565b61026161025c366004611eee565b61114d565b6040516101129291906128e8565b600080600080896001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156102b057600080fd5b505af19250505080156102c1575060015b6102ce57600093506102d3565b600193505b6040517f85dcd60a0000000000000000000000000000000000000000000000000000000081526001600160a01b038b16906385dcd60a90610320908c908c908c908c908c90600401612ac4565b606060405180830381600087803b15801561033a57600080fd5b505af115801561034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037291906123e4565b959c919b5099509397509295505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4d5608a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156103e257600080fd5b505afa1580156103f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041a9190611e9e565b6040517f204e1c7a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063204e1c7a9061046290869060040161274f565b60206040518083038186803b15801561047a57600080fd5b505afa15801561048e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b29190611e9e565b9150505b919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000856001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561051f57600080fd5b505af1925050508015610530575060015b61053d5760009250610542565b600192505b6040517f8ceef9810000000000000000000000000000000000000000000000000000000081526001600160a01b03871690638ceef9819061058990889088906004016129f1565b604080518083038186803b1580156105a057600080fd5b505afa1580156105b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d891906123c1565b93979096509294509192505050565b6000806000836001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561062757600080fd5b505af1925050508015610638575060015b610645576000925061064a565b600192505b836001600160a01b031663dbabbf776040518163ffffffff1660e01b8152600401604080518083038186803b15801561068257600080fd5b505afa158015610696573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ba9190612396565b9395909450915050565b60006106ce611b4f565b60006106d984610386565b90506106e4816112a8565b156106fe576106f284611306565b95506107779350505050565b836001600160a01b0316630cdc105a6040518163ffffffff1660e01b81526004016102806040518083038186803b15801561073857600080fd5b505afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610770919061225d565b9550505050505b602082015161078b576001925050506104b6565b604051630385975360e41b81526001600160a01b038516906338597530906107b99060001990600401612aa4565b600060405180830381600087803b1580156107d357600080fd5b505af19250505080156107e4575060015b6107f3576001925050506104b6565b6000925050506104b6565b6000610808611b6d565b826001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561084357600080fd5b505af1925050508015610854575060015b6108615760009150610866565b600191505b600061087184610386565b905061087c816112a8565b156108a95761088a84611306565b6080870152606086015260408501521515602084015215158252610936565b836001600160a01b0316630cdc105a6040518163ffffffff1660e01b81526004016102806040518083038186803b1580156108e357600080fd5b505afa1580156108f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091b919061225d565b60808701526060860152604085015215156020840152151582525b60808201516020908101516040808501515181517f07c4d486000000000000000000000000000000000000000000000000000000008152915192936000936001600160a01b03909216926307c4d4869260048083019392829003018186803b1580156109a157600080fd5b505afa1580156109b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d99190611e9e565b90508167ffffffffffffffff811180156109f257600080fd5b50604051908082528060200260200182016040528015610a2c57816020015b610a19611bba565b815260200190600190039081610a115790505b5060a085015260005b82811015610a6857610a608560a001518281518110610a5057fe5b60200260200101518389846113de565b600101610a35565b50600160c08501528115610ae057604051630385975360e41b81526001600160a01b03871690633859753090610aa49060001990600401612aa4565b600060405180830381600087803b158015610abe57600080fd5b505af1925050508015610acf575060015b610ad857610ae0565b600060c08501525b505050915091565b6000606080866001600160a01b03166313f07f458787876040518463ffffffff1660e01b8152600401610b1d93929190612af8565b60006040518083038186803b158015610b3557600080fd5b505afa158015610b49573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b719190810190612072565b9050610b7e878783610e33565b925092505094509492505050565b6000806000856001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bcc57600080fd5b505af1925050508015610bdd575060015b610bea5760009250610bef565b600192505b6040517f16b3dd0e0000000000000000000000000000000000000000000000000000000081526001600160a01b038716906316b3dd0e9061058990889088906004016129f1565b6060806060835167ffffffffffffffff81118015610c5357600080fd5b50604051908082528060200260200182016040528015610c7d578160200160208202803683370190505b509250835167ffffffffffffffff81118015610c9857600080fd5b50604051908082528060200260200182016040528015610cc2578160200160208202803683370190505b509150835167ffffffffffffffff81118015610cdd57600080fd5b50604051908082528060200260200182016040528015610d07578160200160208202803683370190505b50905060005b8451811015610e2757610d3b858281518110610d2557fe5b60200260200101516001600160a01b03166112a2565b610d4457610e1f565b848181518110610d5057fe5b60200260200101516001600160a01b031663ccbdbee26040518163ffffffff1660e01b81526004016040805180830381600087803b158015610d9157600080fd5b505af1925050508015610dc1575060408051601f3d908101601f19168201909252610dbe918101906123c1565b60015b610dca57610e1f565b6001868481518110610dd857fe5b60200260200101901515908115158152505081858481518110610df757fe5b60200260200101818152505080848481518110610e1057fe5b60200260200101818152505050505b600101610d0d565b509193909250565b4390565b60006060846001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e7257600080fd5b505af1925050508015610e83575060015b610e905760009150610e95565b600191505b825167ffffffffffffffff81118015610ead57600080fd5b50604051908082528060200260200182016040528015610ee757816020015b610ed4611c17565b815260200190600190039081610ecc5790505b509050610ef2611c51565b6040516204966760e11b81526001600160a01b0387169062092cce90610f1c908890600401612aa4565b6105806040518083038186803b158015610f3557600080fd5b505afa158015610f49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6d91906122ff565b60808101519093509150600090505b855181101561111e576000806000808b6001600160a01b0316637d3ba80f8c8c8881518110610fa757fe5b60200260200101516040518363ffffffff1660e01b8152600401610fcc929190612aad565b6101206040518083038186803b158015610fe557600080fd5b505afa158015610ff9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101d9190612411565b909192939495509091929350909192509050508094508196508295508397505050505089858151811061104c57fe5b602002602001015188868151811061106057fe5b6020026020010151600001906001600160a01b031690816001600160a01b0316815250508188868151811061109157fe5b60200260200101516020018181525050828886815181106110ae57fe5b60200260200101516040018181525050808886815181106110cb57fe5b60209081029190910101519015156060909101526110f36110ec8388611798565b85906117cd565b8886815181106110ff57fe5b602090810291909101015160800152505060019092019150610f7c9050565b505050935093915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611157611c70565b846001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119257600080fd5b505af19250505080156111a3575060015b6111b057600091506111b5565b600191505b60006060866001600160a01b031686866040516024016111d6929190612aad565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16637d3ba80f60e01b179052516112209190612733565b6000604051808303816000865af19150503d806000811461125d576040519150601f19603f3d011682016040523d82523d6000602084013e611262565b606091505b50915091508161128d5760405162461bcd60e51b8152600401611284906129ff565b60405180910390fd5b6112968161183b565b92505050935093915050565b3b151590565b600073ef5d601ea784abd465c788c431d990b620e5fee66001600160a01b03831614806112f1575073755c852d94ffa5e9b6be974a5051d23d5be27e4f6001600160a01b038316145b156112fe575060016104b6565b506000919050565b600080611311611cc2565b611319611ce0565b611321611b4f565b611329611cfe565b866001600160a01b0316630cdc105a6040518163ffffffff1660e01b81526004016102406040518083038186803b15801561136357600080fd5b505afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b91906121a9565b8051875260208082015190880152604080820151908801526060908101519087015260006080870181905260a0870152929a919950975090955091935090915050565b6040516204966760e11b81526001600160a01b0383169062092cce90611408908490600401612aa4565b6105806040518083038186803b15801561142157600080fd5b505afa158015611435573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145991906122ff565b604087018190526001600160a01b03821660208801528683600481111561147c57fe5b600481111561148757fe5b81525050505061149883838361189b565b84606001818152505083602001516001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160006040518083038186803b1580156114de57600080fd5b505afa1580156114f2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261151a919081019061248e565b846080018190525083602001516001600160a01b031663b7e86c1f6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561156157600080fd5b505af1158015611575573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611599919061218f565b151560a0850152602080850151604080517fd1cc997600000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169263d1cc9976926004808401938290030181600087803b1580156115fd57600080fd5b505af1158015611611573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611635919061218f565b151560c0850152604051637d3ba80f60e01b81526001600160a01b03831690637d3ba80f9061166a9084908690600401612aad565b6101206040518083038186803b15801561168357600080fd5b505afa158015611697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bb9190612411565b5050505061010089019390935250505060e08501526040517faeb0abbb0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063aeb0abbb906117379085908590600401612763565b60206040518083038186803b15801561174f57600080fd5b505afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611787919061218f565b151561012090940193909352505050565b6000670de0b6b3a76400006117be6117b08585611990565b670de0b6b3a7640000611a55565b816117c557fe5b059392505050565b60008183038183128015906117e25750838113155b806117f757506000831280156117f757508381135b6118325760405162461bcd60e51b8152600401808060200182810382526024815260200180612bdd6024913960400191505060405180910390fd5b90505b92915050565b611843611c70565b602082518161184e57fe5b061561186c5760405162461bcd60e51b815260040161128490612a36565b815160208301828282015b80831015611892578251825260209283019290910190611877565b50505050919050565b60006060846001600160a01b031663745a3f7485856040518363ffffffff1660e01b81526004016118cd929190612763565b60006040518083038186803b1580156118e557600080fd5b505afa1580156118f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611921919081019061210b565b805190915060018110156119475760405162461bcd60e51b815260040161128490612a6d565b60001960005b828110156119855761197b84828151811061196457fe5b602002602001015183611ad490919063ffffffff16565b915060010161194d565b509695505050505050565b60008261199f57506000611835565b826000191480156119cf57507f800000000000000000000000000000000000000000000000000000000000000082145b15611a0b5760405162461bcd60e51b8152600401808060200182810382526027815260200180612bb66027913960400191505060405180910390fd5b82820282848281611a1857fe5b05146118325760405162461bcd60e51b8152600401808060200182810382526027815260200180612bb66027913960400191505060405180910390fd5b6000808213611aab576040805162461bcd60e51b815260206004820152601f60248201527f726f756e6448616c665570206f6e6c7920737570706f7274732079203e203000604482015290519081900360640190fd5b60008312611ac757611ac08360028405611aea565b9050611835565b61183283600284056117cd565b6000818310611ae35781611832565b5090919050565b6000828201818312801590611aff5750838112155b80611b145750600083128015611b1457508381125b6118325760405162461bcd60e51b8152600401808060200182810382526021815260200180612b956021913960400191505060405180910390fd5b6040518060c001604052806006906020820280368337509192915050565b6040805160e08101825260008082526020820152908101611b8c611cc2565b8152602001611b99611ce0565b8152602001611ba6611b4f565b815260606020820152600060409091015290565b604080516101408101825260008082526020820152908101611bda611c51565b8152602001600081526020016060815260200160001515815260200160001515815260200160008152602001600081526020016000151581525090565b6040518060a0016040528060006001600160a01b031681526020016000815260200160008152602001600015158152602001600081525090565b604051806105400160405280602a906020820280368337509192915050565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600015158152602001600015158152602001600015158152602001600081525090565b6040518060e001604052806007906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b600082601f830112611d2c578081fd5b60405160e0810181811067ffffffffffffffff82111715611d4957fe5b6040529050808260e08101851015611d6057600080fd5b60005b6007811015611d8c578151611d7781612b7c565b83526020928301929190910190600101611d63565b50505092915050565b600082601f830112611da5578081fd5b8135611db8611db382612b32565b612b0e565b818152915060208083019084810181840286018201871015611dd957600080fd5b60005b84811015611e01578135611def81612b7c565b84529282019290820190600101611ddc565b505050505092915050565b600082601f830112611e1c578081fd5b60405160a0810181811067ffffffffffffffff82111715611e3957fe5b6040529050808260a08101851015611e5057600080fd5b60005b6005811015611d8c578151835260209283019290910190600101611e53565b805180151581146104b657600080fd5b600060208284031215611e93578081fd5b813561183281612b7c565b600060208284031215611eaf578081fd5b815161183281612b7c565b600080600060608486031215611ece578182fd5b8335611ed981612b7c565b95602085013595506040909401359392505050565b600080600060608486031215611f02578081fd5b8335611f0d81612b7c565b9250602084013591506040840135611f2481612b7c565b809150509250925092565b60008060008060008060c08789031215611f47578384fd5b8635611f5281612b7c565b9550602087013594506040870135611f6981612b7c565b9350606087013592506080870135611f8081612b7c565b915060a087013563ffffffff81168114611f98578182fd5b809150509295509295509295565b600080600060608486031215611fba578081fd5b8335611fc581612b7c565b925060208401359150604084013567ffffffffffffffff811115611fe7578182fd5b611ff386828701611d95565b9150509250925092565b60008060008060808587031215612012578182fd5b843561201d81612b7c565b966020860135965060408601359560600135945092505050565b600060208284031215612048578081fd5b813567ffffffffffffffff81111561205e578182fd5b61206a84828501611d95565b949350505050565b60006020808385031215612084578182fd5b825167ffffffffffffffff81111561209a578283fd5b8301601f810185136120aa578283fd5b80516120b8611db382612b32565b81815283810190838501858402850186018910156120d4578687fd5b8694505b838510156120ff5780516120eb81612b7c565b8352600194909401939185019185016120d8565b50979650505050505050565b6000602080838503121561211d578182fd5b825167ffffffffffffffff811115612133578283fd5b8301601f81018513612143578283fd5b8051612151611db382612b32565b818152838101908385018584028501860189101561216d578687fd5b8694505b838510156120ff578051835260019490940193918501918501612171565b6000602082840312156121a0578081fd5b61183282611e72565b60008060008060006102408087890312156121c2578384fd5b6121cb87611e72565b955060206121da818901611e72565b95506121e98960408a01611d1c565b94506121f9896101208a01611e0c565b9350886101df89011261220a578283fd5b6122146080612b0e565b806101c08a018b858c011115612228578586fd5b8594505b600485101561224b57805183526001949094019391830191830161222c565b50809450505050509295509295909350565b6000806000806000610280808789031215612276578384fd5b61227f87611e72565b9550602061228e818901611e72565b955061229d8960408a01611d1c565b94506122ad896101208a01611e0c565b9350886101df8901126122be578283fd5b6122c860c0612b0e565b806101c08a018b858c0111156122dc578586fd5b8594505b600685101561224b5780518352600194909401939183019183016122e0565b6000806000610580808587031215612315578182fd5b845160058110612323578283fd5b8094505060208086015161233681612b7c565b9350605f86018713612346578283fd5b612351610540612b0e565b806040880189858a011115612364578586fd5b8594505b602a851015612387578051835260019490940193918301918301612368565b50809450505050509250925092565b600080604083850312156123a8578182fd5b825191506123b860208401611e72565b90509250929050565b600080604083850312156123d3578182fd5b505080516020909101519092909150565b6000806000606084860312156123f8578081fd5b8351925060208401519150604084015190509250925092565b60008060008060008060008060006101208a8c03121561242f578687fd5b8951985060208a0151975060408a0151965060608a0151955060808a0151945061245b60a08b01611e72565b935061246960c08b01611e72565b925061247760e08b01611e72565b91506101008a015190509295985092959850929598565b60006020828403121561249f578081fd5b815167ffffffffffffffff808211156124b6578283fd5b818401915084601f8301126124c9578283fd5b8151818111156124d557fe5b6124e8601f8201601f1916602001612b0e565b91508082528560208285010111156124fe578384fd5b61250f816020840160208601612b50565b50949350505050565b6001600160a01b03169052565b8060005b60078110156125515781516001600160a01b0316845260209384019390910190600101612529565b50505050565b8060005b602a81101561255157815184526020938401939091019060010161255b565b8060005b600581101561255157815184526020938401939091019060010161257e565b6000815180845260208085018081965082840281019150828601855b8581101561268957828403895281516106606125d68683516126f9565b868201516125e688880182612518565b506040808301516125f982890182612557565b505060608201516105808701526080820151816105a088015261261e82880182612707565b91505060a08201516126346105c08801826126f3565b5060c08201516126486105e08801826126f3565b5060e082015161060087015261010082015161062087015261012082015191506126766106408701836126f3565b99860199945050908401906001016125b9565b5091979650505050505050565b8060005b600681101561255157815184526020938401939091019060010161269a565b6000815180845260208085019450808401835b838110156126e8578151875295820195908201906001016126cc565b509495945050505050565b15159052565b6005811061270357fe5b9052565b6000815180845261271f816020860160208601612b50565b601f01601f19169290920160200192915050565b60008251612745818460208701612b50565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b606080825284519082018190526000906020906080840190828801845b828110156127b7578151151584529284019290840190600101612799565b50505083810382850152855180825286830191830190845b818110156127eb578351835292840192918401916001016127cf565b505084810360408601526127ff81876126b9565b98975050505050505050565b901515815260200190565b60006040808301851515845260208281860152818651808452606093508387019150828801865b8281101561288a57815180516001600160a01b0316855285810151868601528781015188860152868101511515878601526080908101519085015260a0909301929084019060010161283d565b50919998505050505050505050565b921515835260208301919091521515604082015260600190565b92151583526020830191909152604082015260600190565b931515845260208401929092526040830152606082015260800190565b600061014082019050831515825282516020830152602083015160408301526040830151606083015260608301516080830152608083015160a083015260a0830151151560c083015260c0830151151560e083015260e0830151610100612951818501836126f3565b8085015161012085015250509392505050565b600083151582526040602083015282511515604083015260208301511515606083015260408301516129996080840182612525565b5060608301516129ad61016084018261257a565b5060808301516129c1610200840182612696565b5060a08301516102c0838101526129dc61030084018261259d565b905060c084015161250f6102e08501826126f3565b918252602082015260400190565b6020808252601f908201527f6661696c20746f207265747269657665206d617267696e206163636f756e7400604082015260600190565b60208082526014908201527f6d616c666f726d656420696e7075742064617461000000000000000000000000604082015260600190565b60208082526010908201527f73796d626f6c206e6f7420666f756e6400000000000000000000000000000000604082015260600190565b90815260200190565b9182526001600160a01b0316602082015260400190565b9485526001600160a01b0393841660208601526040850192909252909116606083015263ffffffff16608082015260a00190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff81118282101715612b2a57fe5b604052919050565b600067ffffffffffffffff821115612b4657fe5b5060209081020190565b60005b83811015612b6b578181015183820152602001612b53565b838111156125515750506000910152565b6001600160a01b0381168114612b9157600080fd5b5056fe5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f775369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f77a26469706673582212201fb602c66071bb588bcff517aa05ac30ec34eb4ab51c9cde67498f43ce47cdce64736f6c63430007040033000000000000000000000000a017b813652b93a0af2887913efcbb4ab250ce65000000000000000000000000129ad040bd127c00d6de9051b3cfe9f3e36453d3
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806377ee51ee1161008c578063b9b3efe911610066578063b9b3efe91461021e578063bc0a260314610233578063c6c1decd14610246578063eb16510d1461024e576100ea565b806377ee51ee146101c85780637e4b4e45146101e9578063a90dc662146101fc576100ea565b80633c070544116100c85780633c0705441461014357806341de031a1461016557806346a83af814610187578063574408c1146101a7576100ea565b806304a6c736146100ef57806315ac72ca1461011b57806334a3cf331461013b575b600080fd5b6101026100fd366004611f2f565b61026f565b60405161011294939291906128cb565b60405180910390f35b61012e610129366004611e82565b610386565b604051610112919061274f565b61012e6104bb565b610156610151366004611eba565b6104df565b604051610112939291906128b3565b610178610173366004611e82565b6105e7565b60405161011293929190612899565b61019a610195366004611e82565b6106c4565b604051610112919061280b565b6101ba6101b5366004611e82565b6107fe565b604051610112929190612964565b6101db6101d6366004611ffd565b610ae8565b604051610112929190612816565b6101566101f7366004611eba565b610b8c565b61020f61020a366004612037565b610c36565b6040516101129392919061277c565b610226610e2f565b6040516101129190612aa4565b6101db610241366004611fa6565b610e33565b61012e611129565b61026161025c366004611eee565b61114d565b6040516101129291906128e8565b600080600080896001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156102b057600080fd5b505af19250505080156102c1575060015b6102ce57600093506102d3565b600193505b6040517f85dcd60a0000000000000000000000000000000000000000000000000000000081526001600160a01b038b16906385dcd60a90610320908c908c908c908c908c90600401612ac4565b606060405180830381600087803b15801561033a57600080fd5b505af115801561034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037291906123e4565b959c919b5099509397509295505050505050565b6000807f000000000000000000000000a017b813652b93a0af2887913efcbb4ab250ce656001600160a01b031663c4d5608a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156103e257600080fd5b505afa1580156103f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041a9190611e9e565b6040517f204e1c7a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063204e1c7a9061046290869060040161274f565b60206040518083038186803b15801561047a57600080fd5b505afa15801561048e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b29190611e9e565b9150505b919050565b7f000000000000000000000000129ad040bd127c00d6de9051b3cfe9f3e36453d381565b6000806000856001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561051f57600080fd5b505af1925050508015610530575060015b61053d5760009250610542565b600192505b6040517f8ceef9810000000000000000000000000000000000000000000000000000000081526001600160a01b03871690638ceef9819061058990889088906004016129f1565b604080518083038186803b1580156105a057600080fd5b505afa1580156105b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d891906123c1565b93979096509294509192505050565b6000806000836001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561062757600080fd5b505af1925050508015610638575060015b610645576000925061064a565b600192505b836001600160a01b031663dbabbf776040518163ffffffff1660e01b8152600401604080518083038186803b15801561068257600080fd5b505afa158015610696573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ba9190612396565b9395909450915050565b60006106ce611b4f565b60006106d984610386565b90506106e4816112a8565b156106fe576106f284611306565b95506107779350505050565b836001600160a01b0316630cdc105a6040518163ffffffff1660e01b81526004016102806040518083038186803b15801561073857600080fd5b505afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610770919061225d565b9550505050505b602082015161078b576001925050506104b6565b604051630385975360e41b81526001600160a01b038516906338597530906107b99060001990600401612aa4565b600060405180830381600087803b1580156107d357600080fd5b505af19250505080156107e4575060015b6107f3576001925050506104b6565b6000925050506104b6565b6000610808611b6d565b826001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561084357600080fd5b505af1925050508015610854575060015b6108615760009150610866565b600191505b600061087184610386565b905061087c816112a8565b156108a95761088a84611306565b6080870152606086015260408501521515602084015215158252610936565b836001600160a01b0316630cdc105a6040518163ffffffff1660e01b81526004016102806040518083038186803b1580156108e357600080fd5b505afa1580156108f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091b919061225d565b60808701526060860152604085015215156020840152151582525b60808201516020908101516040808501515181517f07c4d486000000000000000000000000000000000000000000000000000000008152915192936000936001600160a01b03909216926307c4d4869260048083019392829003018186803b1580156109a157600080fd5b505afa1580156109b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d99190611e9e565b90508167ffffffffffffffff811180156109f257600080fd5b50604051908082528060200260200182016040528015610a2c57816020015b610a19611bba565b815260200190600190039081610a115790505b5060a085015260005b82811015610a6857610a608560a001518281518110610a5057fe5b60200260200101518389846113de565b600101610a35565b50600160c08501528115610ae057604051630385975360e41b81526001600160a01b03871690633859753090610aa49060001990600401612aa4565b600060405180830381600087803b158015610abe57600080fd5b505af1925050508015610acf575060015b610ad857610ae0565b600060c08501525b505050915091565b6000606080866001600160a01b03166313f07f458787876040518463ffffffff1660e01b8152600401610b1d93929190612af8565b60006040518083038186803b158015610b3557600080fd5b505afa158015610b49573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b719190810190612072565b9050610b7e878783610e33565b925092505094509492505050565b6000806000856001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bcc57600080fd5b505af1925050508015610bdd575060015b610bea5760009250610bef565b600192505b6040517f16b3dd0e0000000000000000000000000000000000000000000000000000000081526001600160a01b038716906316b3dd0e9061058990889088906004016129f1565b6060806060835167ffffffffffffffff81118015610c5357600080fd5b50604051908082528060200260200182016040528015610c7d578160200160208202803683370190505b509250835167ffffffffffffffff81118015610c9857600080fd5b50604051908082528060200260200182016040528015610cc2578160200160208202803683370190505b509150835167ffffffffffffffff81118015610cdd57600080fd5b50604051908082528060200260200182016040528015610d07578160200160208202803683370190505b50905060005b8451811015610e2757610d3b858281518110610d2557fe5b60200260200101516001600160a01b03166112a2565b610d4457610e1f565b848181518110610d5057fe5b60200260200101516001600160a01b031663ccbdbee26040518163ffffffff1660e01b81526004016040805180830381600087803b158015610d9157600080fd5b505af1925050508015610dc1575060408051601f3d908101601f19168201909252610dbe918101906123c1565b60015b610dca57610e1f565b6001868481518110610dd857fe5b60200260200101901515908115158152505081858481518110610df757fe5b60200260200101818152505080848481518110610e1057fe5b60200260200101818152505050505b600101610d0d565b509193909250565b4390565b60006060846001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e7257600080fd5b505af1925050508015610e83575060015b610e905760009150610e95565b600191505b825167ffffffffffffffff81118015610ead57600080fd5b50604051908082528060200260200182016040528015610ee757816020015b610ed4611c17565b815260200190600190039081610ecc5790505b509050610ef2611c51565b6040516204966760e11b81526001600160a01b0387169062092cce90610f1c908890600401612aa4565b6105806040518083038186803b158015610f3557600080fd5b505afa158015610f49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6d91906122ff565b60808101519093509150600090505b855181101561111e576000806000808b6001600160a01b0316637d3ba80f8c8c8881518110610fa757fe5b60200260200101516040518363ffffffff1660e01b8152600401610fcc929190612aad565b6101206040518083038186803b158015610fe557600080fd5b505afa158015610ff9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101d9190612411565b909192939495509091929350909192509050508094508196508295508397505050505089858151811061104c57fe5b602002602001015188868151811061106057fe5b6020026020010151600001906001600160a01b031690816001600160a01b0316815250508188868151811061109157fe5b60200260200101516020018181525050828886815181106110ae57fe5b60200260200101516040018181525050808886815181106110cb57fe5b60209081029190910101519015156060909101526110f36110ec8388611798565b85906117cd565b8886815181106110ff57fe5b602090810291909101015160800152505060019092019150610f7c9050565b505050935093915050565b7f000000000000000000000000a017b813652b93a0af2887913efcbb4ab250ce6581565b6000611157611c70565b846001600160a01b0316637086fd326040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119257600080fd5b505af19250505080156111a3575060015b6111b057600091506111b5565b600191505b60006060866001600160a01b031686866040516024016111d6929190612aad565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16637d3ba80f60e01b179052516112209190612733565b6000604051808303816000865af19150503d806000811461125d576040519150601f19603f3d011682016040523d82523d6000602084013e611262565b606091505b50915091508161128d5760405162461bcd60e51b8152600401611284906129ff565b60405180910390fd5b6112968161183b565b92505050935093915050565b3b151590565b600073ef5d601ea784abd465c788c431d990b620e5fee66001600160a01b03831614806112f1575073755c852d94ffa5e9b6be974a5051d23d5be27e4f6001600160a01b038316145b156112fe575060016104b6565b506000919050565b600080611311611cc2565b611319611ce0565b611321611b4f565b611329611cfe565b866001600160a01b0316630cdc105a6040518163ffffffff1660e01b81526004016102406040518083038186803b15801561136357600080fd5b505afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b91906121a9565b8051875260208082015190880152604080820151908801526060908101519087015260006080870181905260a0870152929a919950975090955091935090915050565b6040516204966760e11b81526001600160a01b0383169062092cce90611408908490600401612aa4565b6105806040518083038186803b15801561142157600080fd5b505afa158015611435573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145991906122ff565b604087018190526001600160a01b03821660208801528683600481111561147c57fe5b600481111561148757fe5b81525050505061149883838361189b565b84606001818152505083602001516001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160006040518083038186803b1580156114de57600080fd5b505afa1580156114f2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261151a919081019061248e565b846080018190525083602001516001600160a01b031663b7e86c1f6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561156157600080fd5b505af1158015611575573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611599919061218f565b151560a0850152602080850151604080517fd1cc997600000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169263d1cc9976926004808401938290030181600087803b1580156115fd57600080fd5b505af1158015611611573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611635919061218f565b151560c0850152604051637d3ba80f60e01b81526001600160a01b03831690637d3ba80f9061166a9084908690600401612aad565b6101206040518083038186803b15801561168357600080fd5b505afa158015611697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bb9190612411565b5050505061010089019390935250505060e08501526040517faeb0abbb0000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000129ad040bd127c00d6de9051b3cfe9f3e36453d3169063aeb0abbb906117379085908590600401612763565b60206040518083038186803b15801561174f57600080fd5b505afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611787919061218f565b151561012090940193909352505050565b6000670de0b6b3a76400006117be6117b08585611990565b670de0b6b3a7640000611a55565b816117c557fe5b059392505050565b60008183038183128015906117e25750838113155b806117f757506000831280156117f757508381135b6118325760405162461bcd60e51b8152600401808060200182810382526024815260200180612bdd6024913960400191505060405180910390fd5b90505b92915050565b611843611c70565b602082518161184e57fe5b061561186c5760405162461bcd60e51b815260040161128490612a36565b815160208301828282015b80831015611892578251825260209283019290910190611877565b50505050919050565b60006060846001600160a01b031663745a3f7485856040518363ffffffff1660e01b81526004016118cd929190612763565b60006040518083038186803b1580156118e557600080fd5b505afa1580156118f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611921919081019061210b565b805190915060018110156119475760405162461bcd60e51b815260040161128490612a6d565b60001960005b828110156119855761197b84828151811061196457fe5b602002602001015183611ad490919063ffffffff16565b915060010161194d565b509695505050505050565b60008261199f57506000611835565b826000191480156119cf57507f800000000000000000000000000000000000000000000000000000000000000082145b15611a0b5760405162461bcd60e51b8152600401808060200182810382526027815260200180612bb66027913960400191505060405180910390fd5b82820282848281611a1857fe5b05146118325760405162461bcd60e51b8152600401808060200182810382526027815260200180612bb66027913960400191505060405180910390fd5b6000808213611aab576040805162461bcd60e51b815260206004820152601f60248201527f726f756e6448616c665570206f6e6c7920737570706f7274732079203e203000604482015290519081900360640190fd5b60008312611ac757611ac08360028405611aea565b9050611835565b61183283600284056117cd565b6000818310611ae35781611832565b5090919050565b6000828201818312801590611aff5750838112155b80611b145750600083128015611b1457508381125b6118325760405162461bcd60e51b8152600401808060200182810382526021815260200180612b956021913960400191505060405180910390fd5b6040518060c001604052806006906020820280368337509192915050565b6040805160e08101825260008082526020820152908101611b8c611cc2565b8152602001611b99611ce0565b8152602001611ba6611b4f565b815260606020820152600060409091015290565b604080516101408101825260008082526020820152908101611bda611c51565b8152602001600081526020016060815260200160001515815260200160001515815260200160008152602001600081526020016000151581525090565b6040518060a0016040528060006001600160a01b031681526020016000815260200160008152602001600015158152602001600081525090565b604051806105400160405280602a906020820280368337509192915050565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600015158152602001600015158152602001600015158152602001600081525090565b6040518060e001604052806007906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b600082601f830112611d2c578081fd5b60405160e0810181811067ffffffffffffffff82111715611d4957fe5b6040529050808260e08101851015611d6057600080fd5b60005b6007811015611d8c578151611d7781612b7c565b83526020928301929190910190600101611d63565b50505092915050565b600082601f830112611da5578081fd5b8135611db8611db382612b32565b612b0e565b818152915060208083019084810181840286018201871015611dd957600080fd5b60005b84811015611e01578135611def81612b7c565b84529282019290820190600101611ddc565b505050505092915050565b600082601f830112611e1c578081fd5b60405160a0810181811067ffffffffffffffff82111715611e3957fe5b6040529050808260a08101851015611e5057600080fd5b60005b6005811015611d8c578151835260209283019290910190600101611e53565b805180151581146104b657600080fd5b600060208284031215611e93578081fd5b813561183281612b7c565b600060208284031215611eaf578081fd5b815161183281612b7c565b600080600060608486031215611ece578182fd5b8335611ed981612b7c565b95602085013595506040909401359392505050565b600080600060608486031215611f02578081fd5b8335611f0d81612b7c565b9250602084013591506040840135611f2481612b7c565b809150509250925092565b60008060008060008060c08789031215611f47578384fd5b8635611f5281612b7c565b9550602087013594506040870135611f6981612b7c565b9350606087013592506080870135611f8081612b7c565b915060a087013563ffffffff81168114611f98578182fd5b809150509295509295509295565b600080600060608486031215611fba578081fd5b8335611fc581612b7c565b925060208401359150604084013567ffffffffffffffff811115611fe7578182fd5b611ff386828701611d95565b9150509250925092565b60008060008060808587031215612012578182fd5b843561201d81612b7c565b966020860135965060408601359560600135945092505050565b600060208284031215612048578081fd5b813567ffffffffffffffff81111561205e578182fd5b61206a84828501611d95565b949350505050565b60006020808385031215612084578182fd5b825167ffffffffffffffff81111561209a578283fd5b8301601f810185136120aa578283fd5b80516120b8611db382612b32565b81815283810190838501858402850186018910156120d4578687fd5b8694505b838510156120ff5780516120eb81612b7c565b8352600194909401939185019185016120d8565b50979650505050505050565b6000602080838503121561211d578182fd5b825167ffffffffffffffff811115612133578283fd5b8301601f81018513612143578283fd5b8051612151611db382612b32565b818152838101908385018584028501860189101561216d578687fd5b8694505b838510156120ff578051835260019490940193918501918501612171565b6000602082840312156121a0578081fd5b61183282611e72565b60008060008060006102408087890312156121c2578384fd5b6121cb87611e72565b955060206121da818901611e72565b95506121e98960408a01611d1c565b94506121f9896101208a01611e0c565b9350886101df89011261220a578283fd5b6122146080612b0e565b806101c08a018b858c011115612228578586fd5b8594505b600485101561224b57805183526001949094019391830191830161222c565b50809450505050509295509295909350565b6000806000806000610280808789031215612276578384fd5b61227f87611e72565b9550602061228e818901611e72565b955061229d8960408a01611d1c565b94506122ad896101208a01611e0c565b9350886101df8901126122be578283fd5b6122c860c0612b0e565b806101c08a018b858c0111156122dc578586fd5b8594505b600685101561224b5780518352600194909401939183019183016122e0565b6000806000610580808587031215612315578182fd5b845160058110612323578283fd5b8094505060208086015161233681612b7c565b9350605f86018713612346578283fd5b612351610540612b0e565b806040880189858a011115612364578586fd5b8594505b602a851015612387578051835260019490940193918301918301612368565b50809450505050509250925092565b600080604083850312156123a8578182fd5b825191506123b860208401611e72565b90509250929050565b600080604083850312156123d3578182fd5b505080516020909101519092909150565b6000806000606084860312156123f8578081fd5b8351925060208401519150604084015190509250925092565b60008060008060008060008060006101208a8c03121561242f578687fd5b8951985060208a0151975060408a0151965060608a0151955060808a0151945061245b60a08b01611e72565b935061246960c08b01611e72565b925061247760e08b01611e72565b91506101008a015190509295985092959850929598565b60006020828403121561249f578081fd5b815167ffffffffffffffff808211156124b6578283fd5b818401915084601f8301126124c9578283fd5b8151818111156124d557fe5b6124e8601f8201601f1916602001612b0e565b91508082528560208285010111156124fe578384fd5b61250f816020840160208601612b50565b50949350505050565b6001600160a01b03169052565b8060005b60078110156125515781516001600160a01b0316845260209384019390910190600101612529565b50505050565b8060005b602a81101561255157815184526020938401939091019060010161255b565b8060005b600581101561255157815184526020938401939091019060010161257e565b6000815180845260208085018081965082840281019150828601855b8581101561268957828403895281516106606125d68683516126f9565b868201516125e688880182612518565b506040808301516125f982890182612557565b505060608201516105808701526080820151816105a088015261261e82880182612707565b91505060a08201516126346105c08801826126f3565b5060c08201516126486105e08801826126f3565b5060e082015161060087015261010082015161062087015261012082015191506126766106408701836126f3565b99860199945050908401906001016125b9565b5091979650505050505050565b8060005b600681101561255157815184526020938401939091019060010161269a565b6000815180845260208085019450808401835b838110156126e8578151875295820195908201906001016126cc565b509495945050505050565b15159052565b6005811061270357fe5b9052565b6000815180845261271f816020860160208601612b50565b601f01601f19169290920160200192915050565b60008251612745818460208701612b50565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b606080825284519082018190526000906020906080840190828801845b828110156127b7578151151584529284019290840190600101612799565b50505083810382850152855180825286830191830190845b818110156127eb578351835292840192918401916001016127cf565b505084810360408601526127ff81876126b9565b98975050505050505050565b901515815260200190565b60006040808301851515845260208281860152818651808452606093508387019150828801865b8281101561288a57815180516001600160a01b0316855285810151868601528781015188860152868101511515878601526080908101519085015260a0909301929084019060010161283d565b50919998505050505050505050565b921515835260208301919091521515604082015260600190565b92151583526020830191909152604082015260600190565b931515845260208401929092526040830152606082015260800190565b600061014082019050831515825282516020830152602083015160408301526040830151606083015260608301516080830152608083015160a083015260a0830151151560c083015260c0830151151560e083015260e0830151610100612951818501836126f3565b8085015161012085015250509392505050565b600083151582526040602083015282511515604083015260208301511515606083015260408301516129996080840182612525565b5060608301516129ad61016084018261257a565b5060808301516129c1610200840182612696565b5060a08301516102c0838101526129dc61030084018261259d565b905060c084015161250f6102e08501826126f3565b918252602082015260400190565b6020808252601f908201527f6661696c20746f207265747269657665206d617267696e206163636f756e7400604082015260600190565b60208082526014908201527f6d616c666f726d656420696e7075742064617461000000000000000000000000604082015260600190565b60208082526010908201527f73796d626f6c206e6f7420666f756e6400000000000000000000000000000000604082015260600190565b90815260200190565b9182526001600160a01b0316602082015260400190565b9485526001600160a01b0393841660208601526040850192909252909116606083015263ffffffff16608082015260a00190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff81118282101715612b2a57fe5b604052919050565b600067ffffffffffffffff821115612b4657fe5b5060209081020190565b60005b83811015612b6b578181015183820152602001612b53565b838111156125515750506000910152565b6001600160a01b0381168114612b9157600080fd5b5056fe5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f775369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f77a26469706673582212201fb602c66071bb588bcff517aa05ac30ec34eb4ab51c9cde67498f43ce47cdce64736f6c63430007040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a017b813652b93a0af2887913efcbb4ab250ce65000000000000000000000000129ad040bd127c00d6de9051b3cfe9f3e36453d3
-----Decoded View---------------
Arg [0] : poolCreator_ (address): 0xA017B813652b93a0aF2887913EFCBB4ab250CE65
Arg [1] : inverseStateService_ (address): 0x129AD040Bd127c00d6De9051b3CfE9F3E36453D3
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000a017b813652b93a0af2887913efcbb4ab250ce65
Arg [1] : 000000000000000000000000129ad040bd127c00d6de9051b3cfe9f3e36453d3
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.