Address Details
contract
0x736fdfbd8d7FdCf1440Cc70A4372a297051b2aD0
- Contract Name
- OrderManager
- Creator
- 0xd3c2ab–ffc681 at 0xa6a619–3a079c
- Balance
- 0.046 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 972 Transactions
- Transfers
- 768 Transfers
- Gas Used
- 118,830,975
- Last Balance Update
- 18141077
Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- OrderManager
- Optimization enabled
- true
- Compiler version
- v0.8.16+commit.07a7930e
- Optimization runs
- 800
- EVM Version
- london
- Verified at
- 2023-02-27T14:05:17.194566Z
contracts/core/OrderManager.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "../access/Governable.sol"; import "../interfaces/IOracle.sol"; import "../interfaces/IDex.sol"; contract OrderManager is ReentrancyGuard, Governable { using SafeERC20 for IERC20; struct OpenOrder { address account; bool isLong; bool isTriggerAbove; uint256 productId; uint256 margin; uint256 leverage; uint256 tradeFee; uint256 triggerPrice; uint256 tpPrice; uint256 slPrice; uint256 timestamp; } struct CloseOrder { address account; bool isLong; bool isTriggerAbove; uint256 productId; uint256 size; uint256 triggerPrice; uint256 timestamp; } bool public isInitialized; address public positionManager; address public immutable dex; address public immutable oracle; address public immutable collateralToken; uint256 public maxOpenOrders = 8; uint256 public maxCloseOrders = 8; uint256 public executionFee = 1e15; uint256 private immutable tokenBase; uint256 private constant BASE = 10**8; mapping(bytes32 => OpenOrder) public openOrders; mapping(bytes32 => CloseOrder) public closeOrders; mapping(address => bool) public isKeeper; event CreateOpenOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 margin, uint256 leverage, uint256 tradeFee, uint256 triggerPrice, uint256 tpPrice, uint256 slPrice, uint256 timestamp ); event EditOpenOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 margin, uint256 leverage, uint256 tradeFee, uint256 triggerPrice, uint256 tpPrice, uint256 slPrice, uint256 timestamp ); event CancelOpenOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 margin, uint256 leverage, uint256 tradeFee, uint256 triggerPrice, uint256 tpPrice, uint256 slPrice, uint256 timestamp ); event ExecuteOpenOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 margin, uint256 leverage, uint256 tradeFee, uint256 triggerPrice, uint256 tpPrice, uint256 slPrice, uint256 timestamp, uint256 executionPrice ); event CreateCloseOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 size, uint256 triggerPrice, uint256 timestamp ); event EditCloseOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 size, uint256 triggerPrice, uint256 timestamp ); event CancelCloseOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 size, uint256 triggerPrice, uint256 timestamp ); event ExecuteCloseOrder( bytes32 indexed orderKey, address indexed account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 size, uint256 triggerPrice, uint256 timestamp, uint256 executionPrice ); event ExecuteOpenOrderError(bytes32 indexed orderKey, address indexed account, string executionError); event ExecuteCloseOrderError(bytes32 indexed orderKey, address indexed account, string executionError); event ExecutionFeeRefundError(address indexed account, uint256 totalExecutionFee); event SetKeeper(address keeper, bool isActive); modifier onlyKeeper() { require(isKeeper[msg.sender], "OrderManager: !keeper"); _; } constructor( address _dex, address _oracle, address _collateralToken, uint256 _tokenBase ) { dex = _dex; oracle = _oracle; collateralToken = _collateralToken; tokenBase = _tokenBase; isKeeper[address(this)] = true; } function initialize(address _positionManager) external onlyGov { require(!isInitialized, "OrderManager: already initialized"); isInitialized = true; positionManager = _positionManager; } function createOpenOrder( uint256 productId, bool isLong, bool isTriggerAbove, uint256 margin, uint256 leverage, uint256 triggerPrice, uint256 tpPrice, // no tp set if tpPrice == 0 uint256 slPrice // no sl set if slPrice == 0 ) external payable nonReentrant { uint256 numOfExecutions = 1; if (tpPrice > 0) numOfExecutions += 2; if (slPrice > 0) numOfExecutions += 2; require(msg.value == executionFee * numOfExecutions, "OrderManager: invalid executionFee"); _createOpenOrder( msg.sender, isLong, isTriggerAbove, productId, margin, leverage, triggerPrice, tpPrice, slPrice ); } function _createOpenOrder( address account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 margin, uint256 leverage, uint256 triggerPrice, uint256 tpPrice, uint256 slPrice ) private { IDex(dex).validateOpenPositionRequirements(margin, leverage, productId); uint256 _maxOpenOrders = maxOpenOrders; for (uint256 i = 0; i < _maxOpenOrders; ++i) { bytes32 orderKey = getOrderKey(account, productId, isLong, i); if (openOrders[orderKey].account == address(0)) { uint256 tradeFee = IDex(dex).getTradeFee(margin, leverage, productId); IERC20(collateralToken).safeTransferFrom( account, address(this), ((margin + tradeFee) * tokenBase) / BASE ); openOrders[orderKey] = OpenOrder( account, isLong, isTriggerAbove, productId, margin, leverage, tradeFee, triggerPrice, tpPrice, slPrice, block.timestamp ); emit CreateOpenOrder( orderKey, account, isLong, isTriggerAbove, productId, margin, leverage, tradeFee, triggerPrice, tpPrice, slPrice, block.timestamp ); return; } } revert("OrderManager: maxOpenOrders exceeded"); } function editOpenOrder( bytes32 orderKey, bool isAdjustingTriggerPrice, uint256 triggerPrice, bool isAdjustingTpPrice, uint256 tpPrice, bool isAdjustingSlPrice, uint256 slPrice ) external payable nonReentrant { OpenOrder storage order = openOrders[orderKey]; require(order.account == msg.sender, "OrderManager: !order.account"); if (isAdjustingTriggerPrice) order.triggerPrice = triggerPrice; uint256 numOfExecutions = 0; if (isAdjustingTpPrice) { if (order.tpPrice == 0) { if (tpPrice != 0) { order.tpPrice = tpPrice; numOfExecutions += 2; } } else { if (tpPrice == 0) { order.tpPrice = tpPrice; (bool success, ) = payable(msg.sender).call{value: executionFee}(""); require(success, "OrderManager: failed to send execution fee"); } else { order.tpPrice = tpPrice; } } } if (isAdjustingSlPrice) { if (order.slPrice == 0) { if (slPrice != 0) { order.slPrice = slPrice; numOfExecutions += 2; } } else { if (slPrice == 0) { order.slPrice = slPrice; (bool success, ) = payable(msg.sender).call{value: executionFee}(""); require(success, "OrderManager: failed to send execution fee"); } else { order.slPrice = slPrice; } } } if (numOfExecutions > 0) { require(msg.value == executionFee * numOfExecutions, "OrderManager: invalid executionFee"); } order.timestamp = block.timestamp; emit EditOpenOrder( orderKey, order.account, order.isLong, order.isTriggerAbove, order.productId, order.margin, order.leverage, order.tradeFee, order.triggerPrice, order.tpPrice, order.slPrice, order.timestamp ); } function cancelOpenOrder(bytes32 orderKey) public nonReentrant { OpenOrder memory order = openOrders[orderKey]; require(order.account == msg.sender, "OrderManager: !order.account"); IERC20(collateralToken).safeTransfer(msg.sender, ((order.margin + order.tradeFee) * tokenBase) / BASE); delete openOrders[orderKey]; uint256 numOfExecutions = 1; if (order.tpPrice > 0) numOfExecutions += 2; if (order.slPrice > 0) numOfExecutions += 2; (bool success, ) = payable(msg.sender).call{value: executionFee * numOfExecutions}(""); require(success, "OrderManager: failed to send execution fee"); emit CancelOpenOrder( orderKey, order.account, order.isLong, order.isTriggerAbove, order.productId, order.margin, order.leverage, order.tradeFee, order.triggerPrice, order.tpPrice, order.slPrice, order.timestamp ); } function executeOpenOrder(bytes32 orderKey) external { require(msg.sender == address(this) || isKeeper[msg.sender], "OrderManager: !keeper"); OpenOrder memory order = openOrders[orderKey]; if (order.account == address(0)) return; uint256 currentPrice = validateExecutionPrice( order.isLong, order.isTriggerAbove, order.triggerPrice, order.productId ); IERC20(collateralToken).safeIncreaseAllowance(dex, ((order.margin + order.tradeFee) * tokenBase) / BASE); IDex(dex).openPosition(order.account, order.productId, order.isLong, order.margin, order.leverage); uint256 numOfExecutions = 1; if (order.tpPrice != 0) { _createCloseOrder( order.account, order.isLong, order.isLong, order.productId, (order.margin * order.leverage) / BASE, order.tpPrice ); numOfExecutions += 1; } if (order.slPrice != 0) { _createCloseOrder( order.account, order.isLong, !order.isLong, order.productId, (order.margin * order.leverage) / BASE, order.slPrice ); numOfExecutions += 1; } delete openOrders[orderKey]; (bool success, ) = payable(tx.origin).call{value: executionFee * numOfExecutions}(""); require(success, "OrderManager: failed to send execution fee"); emit ExecuteOpenOrder( orderKey, order.account, order.isLong, order.isTriggerAbove, order.productId, order.margin, order.leverage, order.tradeFee, order.triggerPrice, order.tpPrice, order.slPrice, order.timestamp, currentPrice ); } function createCloseOrder( bool isLong, bool isTriggerAbove, uint256 productId, uint256 size, uint256 triggerPrice ) external payable nonReentrant { require(msg.value == executionFee, "OrderManager: invalid executionFee"); _createCloseOrder(msg.sender, isLong, isTriggerAbove, productId, size, triggerPrice); } function createCloseOrderForTPSL( address account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 size, uint256 triggerPrice ) external payable nonReentrant { require(msg.sender == positionManager, "OrderManager: !positionManager"); require(msg.value == executionFee, "OrderManager: invalid executionFee"); _createCloseOrder(account, isLong, isTriggerAbove, productId, size, triggerPrice); } function _createCloseOrder( address account, bool isLong, bool isTriggerAbove, uint256 productId, uint256 size, uint256 triggerPrice ) private { require(triggerPrice > 0, "OrderManager: triggerPrice cannot be 0"); uint256 _maxCloseOrders = maxCloseOrders; for (uint256 i = 0; i < _maxCloseOrders; ++i) { bytes32 orderKey = getOrderKey(account, productId, isLong, i); if (closeOrders[orderKey].account == address(0)) { closeOrders[orderKey] = CloseOrder( account, isLong, isTriggerAbove, productId, size, triggerPrice, block.timestamp ); emit CreateCloseOrder( orderKey, account, isLong, isTriggerAbove, productId, size, triggerPrice, block.timestamp ); return; } } revert("OrderManager: maxCloseOrders exceeded"); } function editCloseOrder(bytes32 orderKey, uint256 triggerPrice) external nonReentrant { CloseOrder storage order = closeOrders[orderKey]; require(order.account == msg.sender, "OrderManager: !order.account"); order.triggerPrice = triggerPrice; order.timestamp = block.timestamp; emit EditCloseOrder( orderKey, order.account, order.isLong, order.isTriggerAbove, order.productId, order.size, order.triggerPrice, order.timestamp ); } function cancelCloseOrder(bytes32 orderKey) public nonReentrant { require(closeOrders[orderKey].account == msg.sender, "OrderManager: !order.account"); _cancelCloseOrder(orderKey); (bool success, ) = payable(msg.sender).call{value: executionFee}(""); require(success, "OrderManager: failed to send execution fee"); } function cancelActiveCloseOrders( address account, uint256 productId, bool isLong ) external { require(msg.sender == dex, "OrderManager: !dex"); uint256 numOfExecutions = 0; uint256 _maxCloseOrders = maxCloseOrders; for (uint256 i = 0; i < _maxCloseOrders; ++i) { bytes32 orderKey = getOrderKey(account, productId, isLong, i); if (closeOrders[orderKey].account != address(0)) { _cancelCloseOrder(orderKey); numOfExecutions += 1; } } if (numOfExecutions != 0) { uint256 _executionFee = executionFee; (bool success, ) = payable(tx.origin).call{value: _executionFee * numOfExecutions}(""); require(success, "OrderManager: failed to send execution fee"); } } function _cancelCloseOrder(bytes32 orderKey) private { CloseOrder memory order = closeOrders[orderKey]; delete closeOrders[orderKey]; emit CancelCloseOrder( orderKey, order.account, order.isLong, order.isTriggerAbove, order.productId, order.size, order.triggerPrice, order.timestamp ); } function executeCloseOrder(bytes32 orderKey) external { require(msg.sender == address(this) || isKeeper[msg.sender], "OrderManager: !keeper"); CloseOrder memory order = closeOrders[orderKey]; if (order.account == address(0)) return; uint256 currentPrice = validateExecutionPrice( !order.isLong, order.isTriggerAbove, order.triggerPrice, order.productId ); delete closeOrders[orderKey]; IDex(dex).closePosition( order.account, order.productId, order.isLong, (order.size * BASE) / IDex(dex).getPositionLeverage(order.account, order.productId, order.isLong) ); (bool success, ) = payable(tx.origin).call{value: executionFee}(""); require(success, "OrderManager: failed to send execution fee"); emit ExecuteCloseOrder( orderKey, order.account, order.isLong, order.isTriggerAbove, order.productId, order.size, order.triggerPrice, order.timestamp, currentPrice ); } function executeOrdersWithPrices( uint256[] memory productIds, uint256[] memory prices, bytes32[] memory openOrderKeys, bytes32[] memory closeOrderKeys ) external onlyKeeper { IOracle(oracle).setPrices(productIds, prices); for (uint256 i = 0; i < openOrderKeys.length; ++i) { try this.executeOpenOrder(openOrderKeys[i]) {} catch Error(string memory executionError) { emit ExecuteOpenOrderError(openOrderKeys[i], openOrders[openOrderKeys[i]].account, executionError); } catch (bytes memory) {} } for (uint256 i = 0; i < closeOrderKeys.length; ++i) { try this.executeCloseOrder(closeOrderKeys[i]) {} catch Error(string memory executionError) { emit ExecuteCloseOrderError(closeOrderKeys[i], closeOrders[closeOrderKeys[i]].account, executionError); } catch (bytes memory) {} } } function cancelMultipleOrders(bytes32[] memory openOrderKeys, bytes32[] memory closeOrderKeys) external { for (uint256 i = 0; i < openOrderKeys.length; ++i) { cancelOpenOrder(openOrderKeys[i]); } for (uint256 i = 0; i < closeOrderKeys.length; ++i) { cancelCloseOrder(closeOrderKeys[i]); } } function validateExecutionPrice( bool isLong, bool isTriggerAbove, uint256 triggerPrice, uint256 productId ) public view returns (uint256) { uint256 currentPrice = IOracle(oracle).getPrice(productId, isLong); if (isTriggerAbove) { require(currentPrice >= triggerPrice, "OrderManager: current price is below trigger price"); } else { require(currentPrice <= triggerPrice, "OrderManager: current price is above trigger price"); } return currentPrice; } function getOrderKey( address account, uint256 productId, bool isLong, uint256 orderIndex ) public pure returns (bytes32) { return keccak256(abi.encodePacked(account, productId, isLong, orderIndex)); } function getOpenOrder( address account, uint256 productId, bool isLong, uint256 orderIndex ) external view returns ( uint256, uint256, uint256, uint256, bool, uint256, uint256, uint256 ) { OpenOrder memory order = openOrders[getOrderKey(account, productId, isLong, orderIndex)]; return ( order.margin, order.leverage, order.tradeFee, order.triggerPrice, order.isTriggerAbove, order.tpPrice, order.slPrice, order.timestamp ); } function getCloseOrder( address account, uint256 productId, bool isLong, uint256 orderIndex ) external view returns ( uint256, uint256, bool, uint256 ) { CloseOrder memory order = closeOrders[getOrderKey(account, productId, isLong, orderIndex)]; return (order.size, order.triggerPrice, order.isTriggerAbove, order.timestamp); } function getUserOpenOrders( address user, uint256 startId, uint256 endId ) public view returns (bytes32[] memory userOpenOrderKeys, OpenOrder[] memory userOpenOrders) { require(startId > 0, "OrderManager: !startId"); uint256 totalProducts = IDex(dex).totalProducts(); if (endId > totalProducts) endId = totalProducts; uint256 _maxOpenOrders = maxOpenOrders; userOpenOrderKeys = new bytes32[]((endId - startId + 1) * _maxOpenOrders * 2); userOpenOrders = new OpenOrder[]((endId - startId + 1) * _maxOpenOrders * 2); bytes32 orderKey; uint256 count; for (uint256 i = startId; i <= endId; ++i) { for (uint256 j = 0; j < _maxOpenOrders; ++j) { orderKey = getOrderKey(user, i, true, j); if (openOrders[orderKey].account != address(0)) { userOpenOrderKeys[count] = orderKey; userOpenOrders[count++] = openOrders[orderKey]; } orderKey = getOrderKey(user, i, false, j); if (openOrders[orderKey].account != address(0)) { userOpenOrderKeys[count] = orderKey; userOpenOrders[count++] = openOrders[orderKey]; } } } } function getUserCloseOrders( address user, uint256 startId, uint256 endId ) external view returns (bytes32[] memory userCloseOrderKeys, CloseOrder[] memory userCloseOrders) { require(startId > 0, "OrderManager: !startId"); uint256 totalProducts = IDex(dex).totalProducts(); if (endId > totalProducts) endId = totalProducts; uint256 _maxCloseOrders = maxCloseOrders; userCloseOrderKeys = new bytes32[]((endId - startId + 1) * _maxCloseOrders * 2); userCloseOrders = new CloseOrder[]((endId - startId + 1) * _maxCloseOrders * 2); bytes32 orderKey; uint256 count; for (uint256 i = startId; i <= endId; ++i) { for (uint256 j = 0; j < _maxCloseOrders; ++j) { orderKey = getOrderKey(user, i, true, j); if (closeOrders[orderKey].account != address(0)) { userCloseOrderKeys[count] = orderKey; userCloseOrders[count++] = closeOrders[orderKey]; } orderKey = getOrderKey(user, i, false, j); if (closeOrders[orderKey].account != address(0)) { userCloseOrderKeys[count] = orderKey; userCloseOrders[count++] = closeOrders[orderKey]; } } } } function isUserOpenOrderAvailable( address user, uint256 productId, bool isLong ) external view returns (bool) { uint256 _maxOpenOrders = maxOpenOrders; for (uint256 i = 0; i < _maxOpenOrders; ++i) { if (openOrders[getOrderKey(user, productId, isLong, i)].account == address(0)) { return true; } } return false; } function isUserCloseOrderAvailable( address user, uint256 productId, bool isLong ) external view returns (bool) { uint256 _maxCloseOrders = maxCloseOrders; for (uint256 i = 0; i < _maxCloseOrders; ++i) { if (closeOrders[getOrderKey(user, productId, isLong, i)].account == address(0)) { return true; } } return false; } function getUserAvailableOpenOrderSlots( address user, uint256 productId, bool isLong ) external view returns (uint256 availableOpenOrderSlots) { availableOpenOrderSlots = 0; uint256 _maxOpenOrders = maxOpenOrders; for (uint256 i = 0; i < _maxOpenOrders; ++i) { if (openOrders[getOrderKey(user, productId, isLong, i)].account == address(0)) { availableOpenOrderSlots += 1; } } } function getUserAvailableCloseOrderSlots( address user, uint256 productId, bool isLong ) external view returns (uint256 availableCloseOrderSlots) { availableCloseOrderSlots = 0; uint256 _maxCloseOrders = maxCloseOrders; for (uint256 i = 0; i < _maxCloseOrders; ++i) { if (closeOrders[getOrderKey(user, productId, isLong, i)].account == address(0)) { availableCloseOrderSlots += 1; } } } function setMaxOrders(uint256 _maxOpenOrders, uint256 _maxCloseOrders) external onlyGov { require(maxOpenOrders >= 5 && maxCloseOrders >= 5, "OrderManager: !maxNumOfOrders"); maxOpenOrders = _maxOpenOrders; maxCloseOrders = _maxCloseOrders; } function setExecutionFee(uint256 _executionFee) external onlyGov { require(_executionFee <= 1e18); executionFee = _executionFee; } function setKeeper(address _account, bool _isActive) external onlyGov { isKeeper[_account] = _isActive; emit SetKeeper(_account, _isActive); } }
/_openzeppelin/contracts/security/ReentrancyGuard.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
/_openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
/_openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
/_openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
/_openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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"); (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"); (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"); (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"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
/contracts/access/Governable.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Governable { address public gov; event SetGov(address indexed newGov); constructor() { gov = msg.sender; } modifier onlyGov() { require(msg.sender == gov, "Governable: forbidden"); _; } function setGov(address _gov) external onlyGov { gov = _gov; emit SetGov(_gov); } }
/contracts/interfaces/IDex.sol
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IDex { function stakeVaultToCompound(address user, uint256 amount) external; function openPosition( address user, uint256 productId, bool isLong, uint256 margin, uint256 leverage ) external; function validateOpenPositionRequirements( uint256 margin, uint256 leverage, uint256 productId ) external view; function closePosition( address user, uint256 productId, bool isLong, uint256 margin ) external; function liquidatePositions(bytes32[] calldata positionKeys) external; function distributeVaultReward() external returns (uint256); function distributeStakingReward() external returns (uint256); function getVaultShares() external view returns (uint256); function getStakeShares(address user) external view returns (uint256); function getPositionLeverage( address account, uint256 productId, bool isLong ) external view returns (uint256); function minMargin() external view returns (uint256); function totalProducts() external view returns (uint256); function getTradeFee( uint256 margin, uint256 leverage, uint256 productId ) external view returns (uint256); function getPendingVaultReward() external view returns (uint256); function getPendingStakingReward() external view returns (uint256); }
/contracts/interfaces/IOracle.sol
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IOracle { function getPrice(uint256 productId) external view returns (uint256); function getPrice(uint256 productId, bool isLong) external view returns (uint256); function setPrices(uint256[] memory productIds, uint256[] memory prices) external; }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_dex","internalType":"address"},{"type":"address","name":"_oracle","internalType":"address"},{"type":"address","name":"_collateralToken","internalType":"address"},{"type":"uint256","name":"_tokenBase","internalType":"uint256"}]},{"type":"event","name":"CancelCloseOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"size","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CancelOpenOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"margin","internalType":"uint256","indexed":false},{"type":"uint256","name":"leverage","internalType":"uint256","indexed":false},{"type":"uint256","name":"tradeFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"tpPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"slPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CreateCloseOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"size","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CreateOpenOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"margin","internalType":"uint256","indexed":false},{"type":"uint256","name":"leverage","internalType":"uint256","indexed":false},{"type":"uint256","name":"tradeFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"tpPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"slPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"EditCloseOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"size","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"EditOpenOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"margin","internalType":"uint256","indexed":false},{"type":"uint256","name":"leverage","internalType":"uint256","indexed":false},{"type":"uint256","name":"tradeFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"tpPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"slPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExecuteCloseOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"size","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionPrice","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExecuteCloseOrderError","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"string","name":"executionError","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"ExecuteOpenOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"bool","name":"isTriggerAbove","internalType":"bool","indexed":false},{"type":"uint256","name":"productId","internalType":"uint256","indexed":false},{"type":"uint256","name":"margin","internalType":"uint256","indexed":false},{"type":"uint256","name":"leverage","internalType":"uint256","indexed":false},{"type":"uint256","name":"tradeFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"triggerPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"tpPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"slPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionPrice","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExecuteOpenOrderError","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"string","name":"executionError","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"ExecutionFeeRefundError","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint256","name":"totalExecutionFee","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetGov","inputs":[{"type":"address","name":"newGov","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SetKeeper","inputs":[{"type":"address","name":"keeper","internalType":"address","indexed":false},{"type":"bool","name":"isActive","internalType":"bool","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelActiveCloseOrders","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelCloseOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelMultipleOrders","inputs":[{"type":"bytes32[]","name":"openOrderKeys","internalType":"bytes32[]"},{"type":"bytes32[]","name":"closeOrderKeys","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelOpenOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"account","internalType":"address"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"uint256","name":"size","internalType":"uint256"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}],"name":"closeOrders","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"collateralToken","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"createCloseOrder","inputs":[{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"uint256","name":"size","internalType":"uint256"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"createCloseOrderForTPSL","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"uint256","name":"size","internalType":"uint256"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"createOpenOrder","inputs":[{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"margin","internalType":"uint256"},{"type":"uint256","name":"leverage","internalType":"uint256"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"},{"type":"uint256","name":"tpPrice","internalType":"uint256"},{"type":"uint256","name":"slPrice","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"dex","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"editCloseOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"editOpenOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32"},{"type":"bool","name":"isAdjustingTriggerPrice","internalType":"bool"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"},{"type":"bool","name":"isAdjustingTpPrice","internalType":"bool"},{"type":"uint256","name":"tpPrice","internalType":"uint256"},{"type":"bool","name":"isAdjustingSlPrice","internalType":"bool"},{"type":"uint256","name":"slPrice","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeCloseOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeOpenOrder","inputs":[{"type":"bytes32","name":"orderKey","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeOrdersWithPrices","inputs":[{"type":"uint256[]","name":"productIds","internalType":"uint256[]"},{"type":"uint256[]","name":"prices","internalType":"uint256[]"},{"type":"bytes32[]","name":"openOrderKeys","internalType":"bytes32[]"},{"type":"bytes32[]","name":"closeOrderKeys","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"executionFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bool","name":"","internalType":"bool"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCloseOrder","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"uint256","name":"orderIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bool","name":"","internalType":"bool"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getOpenOrder","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"uint256","name":"orderIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getOrderKey","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"uint256","name":"orderIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"availableCloseOrderSlots","internalType":"uint256"}],"name":"getUserAvailableCloseOrderSlots","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"availableOpenOrderSlots","internalType":"uint256"}],"name":"getUserAvailableOpenOrderSlots","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"userCloseOrderKeys","internalType":"bytes32[]"},{"type":"tuple[]","name":"userCloseOrders","internalType":"struct OrderManager.CloseOrder[]","components":[{"type":"address","name":"account","internalType":"address"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"uint256","name":"size","internalType":"uint256"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}]}],"name":"getUserCloseOrders","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"startId","internalType":"uint256"},{"type":"uint256","name":"endId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"userOpenOrderKeys","internalType":"bytes32[]"},{"type":"tuple[]","name":"userOpenOrders","internalType":"struct OrderManager.OpenOrder[]","components":[{"type":"address","name":"account","internalType":"address"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"uint256","name":"margin","internalType":"uint256"},{"type":"uint256","name":"leverage","internalType":"uint256"},{"type":"uint256","name":"tradeFee","internalType":"uint256"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"},{"type":"uint256","name":"tpPrice","internalType":"uint256"},{"type":"uint256","name":"slPrice","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}]}],"name":"getUserOpenOrders","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"startId","internalType":"uint256"},{"type":"uint256","name":"endId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"gov","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_positionManager","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isInitialized","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isKeeper","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isUserCloseOrderAvailable","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isUserOpenOrderAvailable","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxCloseOrders","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxOpenOrders","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"account","internalType":"address"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"productId","internalType":"uint256"},{"type":"uint256","name":"margin","internalType":"uint256"},{"type":"uint256","name":"leverage","internalType":"uint256"},{"type":"uint256","name":"tradeFee","internalType":"uint256"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"},{"type":"uint256","name":"tpPrice","internalType":"uint256"},{"type":"uint256","name":"slPrice","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}],"name":"openOrders","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"oracle","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"positionManager","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setExecutionFee","inputs":[{"type":"uint256","name":"_executionFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setGov","inputs":[{"type":"address","name":"_gov","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setKeeper","inputs":[{"type":"address","name":"_account","internalType":"address"},{"type":"bool","name":"_isActive","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxOrders","inputs":[{"type":"uint256","name":"_maxOpenOrders","internalType":"uint256"},{"type":"uint256","name":"_maxCloseOrders","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"validateExecutionPrice","inputs":[{"type":"bool","name":"isLong","internalType":"bool"},{"type":"bool","name":"isTriggerAbove","internalType":"bool"},{"type":"uint256","name":"triggerPrice","internalType":"uint256"},{"type":"uint256","name":"productId","internalType":"uint256"}]}]
Contract Creation Code
0x6101006040526008600355600860045566038d7ea4c680006005553480156200002757600080fd5b506040516200529b3803806200529b8339810160408190526200004a91620000bc565b6001600081815581546001600160a01b031916331782556001600160a01b0395861660805293851660a0529190931660c05260e092909252308152600860205260409020805460ff191690911790556200010e565b80516001600160a01b0381168114620000b757600080fd5b919050565b60008060008060808587031215620000d357600080fd5b620000de856200009f565b9350620000ee602086016200009f565b9250620000fe604086016200009f565b6060959095015193969295505050565b60805160a05160c05160e0516150ea620001b16000396000818161122b0152818161284f015261422a01526000818161079b0152818161127c015281816128a0015261427101526000818161063001528181612369015261326c01526000818161053801528181610a3301528181611205015281816112f201528181611cfd01528181612dfc015281816133e4015281816140a501526141a901526150ea6000f3fe6080604052600436106102a05760003560e01c8063791b98bc1161016e578063c4d66de8116100cb578063e084f3581161007f578063ee0d84e211610064578063ee0d84e21461093a578063f3fadffb1461095a578063fa6165181461097a57600080fd5b8063e084f35814610870578063e57593131461091a57600080fd5b8063cb33d0be116100b0578063cb33d0be14610810578063cfad57a214610830578063d1b9e8531461085057600080fd5b8063c4d66de8146107d0578063c817b238146107f057600080fd5b80639af9255c11610122578063aae4b73411610107578063aae4b73414610769578063b2016bd414610789578063c0848ebe146107bd57600080fd5b80639af9255c146106d8578063a1f20fbf1461074957600080fd5b80637e7e3159116101535780637e7e3159146106525780638c4dc9d91461067257806390bb9e6a1461069257600080fd5b8063791b98bc146105fe5780637dc0d1d01461061e57600080fd5b806341e276e91161021c5780636962fe56116101d05780636f314266116101b55780636f3142661461059d57806373e15834146105cb57806375b77945146105eb57600080fd5b80636962fe561461055a5780636ba42aaa1461056d57600080fd5b806352a1c2a71161020157806352a1c2a71461042657806366cb458114610446578063692058c21461052657600080fd5b806341e276e9146103f05780634aa38c6d1461040657600080fd5b8063237aae9c1161027357806337a063d21161025857806337a063d214610399578063392e53cd146103b957806340e9903b146103da57600080fd5b8063237aae9c1461035557806336e5e4e21461037557600080fd5b806312d43a51146102a55780631683d218146102e25780631844f44f1461031057806320cd610414610325575b600080fd5b3480156102b157600080fd5b506001546102c5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102ee57600080fd5b506103026102fd3660046147d9565b6109d7565b6040516102d9929190614847565b61032361031e366004614925565b610f00565b005b34801561033157600080fd5b50610345610340366004614988565b611028565b60405190151581526020016102d9565b34801561036157600080fd5b506103236103703660046149c8565b6110ca565b34801561038157600080fd5b5061038b60045481565b6040519081526020016102d9565b3480156103a557600080fd5b506103236103b43660046149c8565b6115fe565b3480156103c557600080fd5b5060015461034590600160a01b900460ff1681565b3480156103e657600080fd5b5061038b60055481565b3480156103fc57600080fd5b5061038b60035481565b34801561041257600080fd5b506103236104213660046149c8565b61166a565b34801561043257600080fd5b506103236104413660046149e1565b6117e5565b34801561045257600080fd5b506104c36104613660046149c8565b60066020819052600091825260409091208054600182015460028301546003840154600485015460058601549686015460078701546008909701546001600160a01b0387169860ff600160a01b8904811699600160a81b90990416979092918b565b604080516001600160a01b03909c168c5299151560208c0152971515988a01989098526060890195909552608088019390935260a087019190915260c086015260e0850152610100840152610120830191909152610140820152610160016102d9565b34801561053257600080fd5b506102c57f000000000000000000000000000000000000000000000000000000000000000081565b610323610568366004614a03565b6118a4565b34801561057957600080fd5b50610345610588366004614a75565b60086020526000908152604090205460ff1681565b3480156105a957600080fd5b506105bd6105b83660046147d9565b611ca6565b6040516102d9929190614a90565b3480156105d757600080fd5b5061038b6105e6366004614988565b61214a565b6103236105f9366004614b23565b6121ea565b34801561060a57600080fd5b506002546102c5906001600160a01b031681565b34801561062a57600080fd5b506102c57f000000000000000000000000000000000000000000000000000000000000000081565b34801561065e57600080fd5b5061032361066d366004614c69565b6122f3565b34801561067e57600080fd5b5061032361068d3660046149c8565b6126fa565b34801561069e57600080fd5b506106b26106ad366004614d16565b612aed565b6040805194855260208501939093529015159183019190915260608201526080016102d9565b3480156106e457600080fd5b5061038b6106f3366004614d16565b6040516001600160601b0319606086901b1660208201526034810184905282151560f81b605482015260558101829052600090607501604051602081830303815290604052805190602001209050949350505050565b34801561075557600080fd5b50610323610764366004614d5c565b612be9565b34801561077557600080fd5b506103236107843660046149c8565b612c6b565b34801561079557600080fd5b506102c57f000000000000000000000000000000000000000000000000000000000000000081565b6103236107cb366004614dc0565b613060565b3480156107dc57600080fd5b506103236107eb366004614a75565b61312d565b3480156107fc57600080fd5b5061038b61080b366004614e11565b613241565b34801561081c57600080fd5b5061032361082b366004614988565b6133d9565b34801561083c57600080fd5b5061032361084b366004614a75565b6135ba565b34801561085c57600080fd5b5061032361086b366004614e57565b613663565b34801561087c57600080fd5b506108d561088b3660046149c8565b600760205260009081526040902080546001820154600283015460038401546004909401546001600160a01b0384169460ff600160a01b8604811695600160a81b90041693929187565b604080516001600160a01b0390981688529515156020880152931515948601949094526060850191909152608084015260a083019190915260c082015260e0016102d9565b34801561092657600080fd5b50610345610935366004614988565b613718565b34801561094657600080fd5b5061038b610955366004614988565b6137ac565b34801561096657600080fd5b506103236109753660046149e1565b613843565b34801561098657600080fd5b5061099a610995366004614d16565b61399c565b6040805198895260208901979097529587019490945260608601929092521515608085015260a084015260c083015260e0820152610100016102d9565b60608060008411610a2f5760405162461bcd60e51b815260206004820152601660248201527f4f726465724d616e616765723a2021737461727449640000000000000000000060448201526064015b60405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639b9d326d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab39190614e8e565b905080841115610ac1578093505b60035480610acf8787614ebd565b610ada906001614ed6565b610ae49190614ee9565b610aef906002614ee9565b67ffffffffffffffff811115610b0757610b07614b91565b604051908082528060200260200182016040528015610b30578160200160208202803683370190505b50935080610b3e8787614ebd565b610b49906001614ed6565b610b539190614ee9565b610b5e906002614ee9565b67ffffffffffffffff811115610b7657610b76614b91565b604051908082528060200260200182016040528015610c1157816020015b610bfe60405180610160016040528060006001600160a01b0316815260200160001515815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610b945790505b509250600080875b878111610ef35760005b84811015610ee2576040805160608d901b6001600160601b03191660208083019190915260348201859052600160f81b6054830152605580830185905283518084039091018152607590920190925280519101206000818152600660205260409020549094506001600160a01b031615610d805783888481518110610caa57610caa614f08565b6020908102919091018101919091526000858152600680835260409182902082516101608101845281546001600160a01b038116825260ff600160a01b82048116151596830196909652600160a81b90049094161515928401929092526001820154606084015260028201546080840152600382015460a0840152600482015460c0840152600582015460e08401528101546101008301526007810154610120830152600801546101408201528784610d6281614f1e565b955081518110610d7457610d74614f08565b60200260200101819052505b6040805160608d901b6001600160601b0319166020808301919091526034820185905260006054830152605580830185905283518084039091018152607590920190925280519101206000818152600660205260409020549094506001600160a01b031615610ed25783888481518110610dfc57610dfc614f08565b6020908102919091018101919091526000858152600680835260409182902082516101608101845281546001600160a01b038116825260ff600160a01b82048116151596830196909652600160a81b90049094161515928401929092526001820154606084015260028201546080840152600382015460a0840152600482015460c0840152600582015460e08401528101546101008301526007810154610120830152600801546101408201528784610eb481614f1e565b955081518110610ec657610ec6614f08565b60200260200101819052505b610edb81614f1e565b9050610c23565b50610eec81614f1e565b9050610c19565b5050505050935093915050565b600260005403610f525760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b60026000819055546001600160a01b03163314610fb15760405162461bcd60e51b815260206004820152601e60248201527f4f726465724d616e616765723a2021706f736974696f6e4d616e6167657200006044820152606401610a26565b600554341461100d5760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b61101b868686868686613ae2565b5050600160005550505050565b600454600090815b818110156110bc57604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600790915220546001600160a01b03166110ac576001925050506110c3565b6110b581614f1e565b9050611030565b5060009150505b9392505050565b333014806110e757503360009081526008602052604090205460ff165b6111335760405162461bcd60e51b815260206004820152601560248201527f4f726465724d616e616765723a20216b656570657200000000000000000000006044820152606401610a26565b60008181526006602081815260409283902083516101608101855281546001600160a01b03811680835260ff600160a01b83048116151595840195909552600160a81b9091049093161515948101949094526001810154606085015260028101546080850152600381015460a0850152600481015460c0850152600581015460e08501529182015461010084015260078201546101208401526008909101546101408301526111e0575050565b60006111fe826020015183604001518460e001518560600151613241565b90506112a37f00000000000000000000000000000000000000000000000000000000000000006305f5e1007f00000000000000000000000000000000000000000000000000000000000000008560c00151866080015161125e9190614ed6565b6112689190614ee9565b6112729190614f37565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190613db1565b815160608301516020840151608085015160a0860151604051639267fbbd60e01b81526001600160a01b03958616600482015260248101949094529115156044840152606483015260848201527f000000000000000000000000000000000000000000000000000000000000000090911690639267fbbd9060a401600060405180830381600087803b15801561133857600080fd5b505af115801561134c573d6000803e3d6000fd5b50505061010083015160019150156113b1576113a383600001518460200151856020015186606001516305f5e1008860a00151896080015161138e9190614ee9565b6113989190614f37565b886101000151613ae2565b6113ae600182614ed6565b90505b61012083015115611410576114028360000151846020015185602001511586606001516305f5e1008860a0015189608001516113ed9190614ee9565b6113f79190614f37565b886101200151613ae2565b61140d600182614ed6565b90505b60008481526006602081905260408220805475ffffffffffffffffffffffffffffffffffffffffffff1916815560018101839055600281018390556003810183905560048101839055600580820184905591810183905560078101839055600801829055543290611482908490614ee9565b604051600081818185875af1925050503d80600081146114be576040519150601f19603f3d011682016040523d82523d6000602084013e6114c3565b606091505b50509050806115275760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b83600001516001600160a01b0316857f07cc7aa86de748bd1ef6a42d07028c18d69cb3cf9556ff2d219aae37aa94350d86602001518760400151886060015189608001518a60a001518b60c001518c60e001518d61010001518e61012001518f61014001518f6040516115ef9b9a999897969594939291909a15158b5298151560208b015260408a01979097526060890195909552608088019390935260a087019190915260c086015260e08501526101008401526101208301526101408201526101600190565b60405180910390a35050505050565b6001546001600160a01b031633146116505760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b670de0b6b3a764000081111561166557600080fd5b600555565b6002600054036116bc5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b60026000908155818152600760205260409020546001600160a01b031633146117275760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b61173081613ec9565b60055460405160009133918381818185875af1925050503d8060008114611773576040519150601f19603f3d011682016040523d82523d6000602084013e611778565b606091505b50509050806117dc5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50506001600055565b6001546001600160a01b031633146118375760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b60056003541015801561184d5750600560045410155b6118995760405162461bcd60e51b815260206004820152601d60248201527f4f726465724d616e616765723a20216d61784e756d4f664f72646572730000006044820152606401610a26565b600391909155600455565b6002600054036118f65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b6002600090815587815260066020526040902080546001600160a01b031633146119625760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b861561197057600581018690555b60008515611a6d5781600601546000036119a457841561199f576006820185905561199c600282614ed6565b90505b611a6d565b84600003611a65576006820185905560055460405160009133918381818185875af1925050503d80600081146119f6576040519150601f19603f3d011682016040523d82523d6000602084013e6119fb565b606091505b5050905080611a5f5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50611a6d565b600682018590555b8315611b68578160070154600003611a9f578215611a9a5760078201839055611a97600282614ed6565b90505b611b68565b82600003611b60576007820183905560055460405160009133918381818185875af1925050503d8060008114611af1576040519150601f19603f3d011682016040523d82523d6000602084013e611af6565b606091505b5050905080611b5a5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50611b68565b600782018390555b8015611bd55780600554611b7c9190614ee9565b3414611bd55760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b4260088301819055825460018401546002850154600386015460048701546005880154600689015460078a01546040805160ff600160a01b8b04811615158252600160a81b8b041615156020820152908101979097526060870195909552608086019390935260a085019190915260c084015260e08301526101008201526101208101929092526001600160a01b0316908a907f0a5e00c5dd98a039848cc82972d5b769df4d9e8889c0d7dda308a38f7cdb18a9906101400160405180910390a35050600160005550505050505050565b60608060008411611cf95760405162461bcd60e51b815260206004820152601660248201527f4f726465724d616e616765723a202173746172744964000000000000000000006044820152606401610a26565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639b9d326d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d9190614e8e565b905080841115611d8b578093505b60045480611d998787614ebd565b611da4906001614ed6565b611dae9190614ee9565b611db9906002614ee9565b67ffffffffffffffff811115611dd157611dd1614b91565b604051908082528060200260200182016040528015611dfa578160200160208202803683370190505b50935080611e088787614ebd565b611e13906001614ed6565b611e1d9190614ee9565b611e28906002614ee9565b67ffffffffffffffff811115611e4057611e40614b91565b604051908082528060200260200182016040528015611ebe57816020015b611eab6040518060e0016040528060006001600160a01b03168152602001600015158152602001600015158152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081611e5e5790505b509250600080875b878111610ef35760005b84811015612139576040805160608d901b6001600160601b03191660208083019190915260348201859052600160f81b6054830152605580830185905283518084039091018152607590920190925280519101206000818152600760205260409020549094506001600160a01b0316156120025783888481518110611f5757611f57614f08565b602090810291909101810191909152600085815260078252604090819020815160e08101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b90049093161515918301919091526001810154606083015260028101546080830152600381015460a08301526004015460c08201528784611fe481614f1e565b955081518110611ff657611ff6614f08565b60200260200101819052505b6040805160608d901b6001600160601b0319166020808301919091526034820185905260006054830152605580830185905283518084039091018152607590920190925280519101206000818152600760205260409020549094506001600160a01b031615612129578388848151811061207e5761207e614f08565b602090810291909101810191909152600085815260078252604090819020815160e08101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b90049093161515918301919091526001810154606083015260028101546080830152600381015460a08301526004015460c0820152878461210b81614f1e565b95508151811061211d5761211d614f08565b60200260200101819052505b61213281614f1e565b9050611ed0565b5061214381614f1e565b9050611ec6565b600354600090815b818110156121e157604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600690915220546001600160a01b03166121d1576121ce600184614ed6565b92505b6121da81614f1e565b9050612152565b50509392505050565b60026000540361223c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b60026000556001821561225757612254600282614ed6565b90505b811561226b57612268600282614ed6565b90505b806005546122799190614ee9565b34146122d25760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b6122e33389898c8a8a8a8a8a614081565b5050600160005550505050505050565b3360009081526008602052604090205460ff166123525760405162461bcd60e51b815260206004820152601560248201527f4f726465724d616e616765723a20216b656570657200000000000000000000006044820152606401610a26565b604051630682f55760e51b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d05eaae0906123a09087908790600401614f59565b600060405180830381600087803b1580156123ba57600080fd5b505af11580156123ce573d6000803e3d6000fd5b5050505060005b825181101561256257306001600160a01b031663237aae9c8483815181106123ff576123ff614f08565b60200260200101516040518263ffffffff1660e01b815260040161242591815260200190565b600060405180830381600087803b15801561243f57600080fd5b505af1925050508015612450575060015b6125525761245c614f7e565b806308c379a00361251e5750612470614f9a565b8061247b5750612520565b6006600085848151811061249157612491614f08565b6020026020010151815260200190815260200160002060000160009054906101000a90046001600160a01b03166001600160a01b03168483815181106124d9576124d9614f08565b60200260200101517f81302fc3204662085acace33c36464c982ee6cd7aa54f729176650cc51a4b861836040516125109190615048565b60405180910390a350612552565b505b3d80801561254a576040519150601f19603f3d011682016040523d82523d6000602084013e61254f565b606091505b50505b61255b81614f1e565b90506123d5565b5060005b81518110156126f357306001600160a01b031663aae4b73483838151811061259057612590614f08565b60200260200101516040518263ffffffff1660e01b81526004016125b691815260200190565b600060405180830381600087803b1580156125d057600080fd5b505af19250505080156125e1575060015b6126e3576125ed614f7e565b806308c379a0036126af5750612601614f9a565b8061260c57506126b1565b6007600084848151811061262257612622614f08565b6020026020010151815260200190815260200160002060000160009054906101000a90046001600160a01b03166001600160a01b031683838151811061266a5761266a614f08565b60200260200101517f48b2b3f3b7cf047cbc676166e59b80a9aea26e67f2a964fcd4a5a945dec27a6f836040516126a19190615048565b60405180910390a3506126e3565b505b3d8080156126db576040519150601f19603f3d011682016040523d82523d6000602084013e6126e0565b606091505b50505b6126ec81614f1e565b9050612566565b5050505050565b60026000540361274c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b600260008181558281526006602081815260409283902083516101608101855281546001600160a01b03811680835260ff600160a01b83048116151595840195909552600160a81b90910490931615159481019490945260018101546060850152938401546080840152600384015460a0840152600484015460c0840152600584015460e08401529083015461010083015260078301546101208301526008909201546101408201529033146128445760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b6128c7336305f5e1007f00000000000000000000000000000000000000000000000000000000000000008460c0015185608001516128829190614ed6565b61288c9190614ee9565b6128969190614f37565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691906144d8565b60008281526006602081905260408220805475ffffffffffffffffffffffffffffffffffffffffffff1916815560018082018490556002820184905560038201849055600482018490556005820184905591810183905560078101839055600801919091556101008201511561294557612942600282614ed6565b90505b6101208201511561295e5761295b600282614ed6565b90505b6000336001600160a01b0316826005546129789190614ee9565b604051600081818185875af1925050503d80600081146129b4576040519150601f19603f3d011682016040523d82523d6000602084013e6129b9565b606091505b5050905080612a1d5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b82600001516001600160a01b0316847f49358803a7ae36469d52afc763a7489ec58204d535ff56c6af7af33492244b4985602001518660400151876060015188608001518960a001518a60c001518b60e001518c61010001518d61012001518e6101400151604051612ada9a999897969594939291909915158a5297151560208a015260408901969096526060880194909452608087019290925260a086015260c085015260e08401526101008301526101208201526101400190565b60405180910390a3505060016000555050565b600080600080600060076000612b568b8b8b8b6040516001600160601b0319606086901b1660208201526034810184905282151560f81b605482015260558101829052600090607501604051602081830303815290604052805190602001209050949350505050565b81526020808201929092526040908101600020815160e08101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b9004909316151591830182905260018101546060840152600281015460808401819052600382015460a0850181905260049092015460c0909401849052975095509350915050945094509450949050565b60005b8251811015612c2757612c17838281518110612c0a57612c0a614f08565b60200260200101516126fa565b612c2081614f1e565b9050612bec565b5060005b8151811015612c6657612c56828281518110612c4957612c49614f08565b602002602001015161166a565b612c5f81614f1e565b9050612c2b565b505050565b33301480612c8857503360009081526008602052604090205460ff165b612cd45760405162461bcd60e51b815260206004820152601560248201527f4f726465724d616e616765723a20216b656570657200000000000000000000006044820152606401610a26565b600081815260076020908152604091829020825160e08101845281546001600160a01b03811680835260ff600160a01b83048116151595840195909552600160a81b9091049093161515938101939093526001810154606084015260028101546080840152600381015460a08401526004015460c0830152612d54575050565b6000612d7382602001511583604001518460a001518560600151613241565b6000848152600760209081526040808320805475ffffffffffffffffffffffffffffffffffffffffffff1916815560018101849055600281018490556003810184905560049081019390935585516060870151928701519151634df8059360e11b81526001600160a01b03808316958201959095526024810184905282151560448201529495507f0000000000000000000000000000000000000000000000000000000000000000909316936314d8353f939291908590639bf00b2690606401602060405180830381865afa158015612e50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e749190614e8e565b6305f5e1008860800151612e889190614ee9565b612e929190614f37565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b0390941660048501526024840192909252151560448301526064820152608401600060405180830381600087803b158015612eff57600080fd5b505af1158015612f13573d6000803e3d6000fd5b5050600554604051600093503292508381818185875af1925050503d8060008114612f5a576040519150601f19603f3d011682016040523d82523d6000602084013e612f5f565b606091505b5050905080612fc35760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b82600001516001600160a01b0316847f47036c05d3bcca301b675f2154fca0f55a59c635efd8b997a417d10b0c3ce1d185602001518660400151876060015188608001518960a001518a60c001518a60405161305297969594939291909615158752941515602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b60405180910390a350505050565b6002600054036130b25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b600260005560055434146131135760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b613121338686868686613ae2565b50506001600055505050565b6001546001600160a01b0316331461317f5760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b600154600160a01b900460ff16156131e35760405162461bcd60e51b815260206004820152602160248201527f4f726465724d616e616765723a20616c726561647920696e697469616c697a656044820152601960fa1b6064820152608401610a26565b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055600280546001600160a01b0390921673ffffffffffffffffffffffffffffffffffffffff19909216919091179055565b604051632b82db0d60e11b815260048101829052841515602482015260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635705b61a90604401602060405180830381865afa1580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d79190614e8e565b9050841561335a57838110156133555760405162461bcd60e51b815260206004820152603260248201527f4f726465724d616e616765723a2063757272656e74207072696365206973206260448201527f656c6f77207472696767657220707269636500000000000000000000000000006064820152608401610a26565b6133d0565b838111156133d05760405162461bcd60e51b815260206004820152603260248201527f4f726465724d616e616765723a2063757272656e74207072696365206973206160448201527f626f7665207472696767657220707269636500000000000000000000000000006064820152608401610a26565b95945050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146134515760405162461bcd60e51b815260206004820152601260248201527f4f726465724d616e616765723a202164657800000000000000000000000000006044820152606401610a26565b600454600090815b818110156134f557604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b60548301526055808301859052835180840390910181526075909201835281519181019190912060008181526007909252919020546001600160a01b0316156134e4576134d681613ec9565b6134e1600185614ed6565b93505b506134ee81614f1e565b9050613459565b5081156126f35760055460003261350c8584614ee9565b604051600081818185875af1925050503d8060008114613548576040519150601f19603f3d011682016040523d82523d6000602084013e61354d565b606091505b50509050806135b15760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50505050505050565b6001546001600160a01b0316331461360c5760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f91a8c1cc2d4a3bb60738481947a00cbb9899c822916694cf8bb1d68172fdcd5490600090a250565b6001546001600160a01b031633146136b55760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b6001600160a01b038216600081815260086020908152604091829020805460ff19168515159081179091558251938452908301527f8c2ff6748f99f65f4ebf8a1e973a289bad216c4d5b20fda1940d9e01118ae42a910160405180910390a15050565b600354600090815b818110156110bc57604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600690915220546001600160a01b031661379c576001925050506110c3565b6137a581614f1e565b9050613720565b600454600090815b818110156121e157604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600790915220546001600160a01b031661383357613830600184614ed6565b92505b61383c81614f1e565b90506137b4565b6002600054036138955760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b6002600090815582815260076020526040902080546001600160a01b031633146139015760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b6003810182905542600482018190558154600183015460028401546040805160ff600160a01b8604811615158252600160a81b860416151560208201529081019290925260608201526080810185905260a08101929092526001600160a01b03169084907f6911fa079056e89ec24445683aa16240daff19f20221857b69ace7f7f2167f8a9060c00160405180910390a35050600160005550565b600080600080600080600080600060066000613a0b8f8f8f8f6040516001600160601b0319606086901b1660208201526034810184905282151560f81b605482015260558101829052600090607501604051602081830303815290604052805190602001209050949350505050565b8152602080820192909252604090810160002081516101608101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b9004909316151591830182905260018101546060840152600281015460808401819052600382015460a08501819052600483015460c08601819052600584015460e087018190526006850154610100880181905260078601546101208901819052600890960154610140909801889052939f50919d509b509950919750909550935091505094995094995094999196509450565b60008111613b585760405162461bcd60e51b815260206004820152602660248201527f4f726465724d616e616765723a207472696767657250726963652063616e6e6f60448201527f74206265203000000000000000000000000000000000000000000000000000006064820152608401610a26565b60045460005b81811015613d3a57604080516001600160601b031960608b901b166020808301919091526034820188905289151560f81b60548301526055808301859052835180840390910181526075909201835281519181019190912060008181526007909252919020546001600160a01b0316613d29576040805160e0810182526001600160a01b03808c168083528b151560208085019182528c1515858701908152606086018d8152608087018d815260a088018d81524260c08a0181815260008d81526007909752958b902099518a54975195511515600160a81b027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff961515600160a01b027fffffffffffffffffffffff00000000000000000000000000000000000000000090991691909a16179690961793909316969096178755516001870155935160028601559251600385015591516004909301929092559151909183917fd1d8633d045dfd8d52789d0505215f098a1777a0a0a8ac150c94a16d0231df1091613d19918d918d918d918d918d91909515158652931515602086015260408501929092526060840152608083015260a082015260c00190565b60405180910390a3505050613da9565b50613d3381614f1e565b9050613b5e565b5060405162461bcd60e51b815260206004820152602560248201527f4f726465724d616e616765723a206d6178436c6f73654f72646572732065786360448201527f65656465640000000000000000000000000000000000000000000000000000006064820152608401610a26565b505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015613e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e269190614e8e565b613e309190614ed6565b6040516001600160a01b038516602482015260448101829052909150613ec390859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614508565b50505050565b6000600760008381526020019081526020016000206040518060e00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900460ff161515151581526020016000820160159054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060076000838152602001908152602001600020600080820160006101000a8154906001600160a01b0302191690556000820160146101000a81549060ff02191690556000820160156101000a81549060ff02191690556001820160009055600282016000905560038201600090556004820160009055505080600001516001600160a01b0316827ff88686450cd096feaf4c9c73e01e80cc376845eac25202501d46a386ceef7cd583602001518460400151856060015186608001518760a001518860c00151604051614075969594939291909515158652931515602086015260408501929092526060840152608083015260a082015260c00190565b60405180910390a35050565b60405163021707f360e41b81526004810186905260248101859052604481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321707f309060640160006040518083038186803b1580156140ef57600080fd5b505afa158015614103573d6000803e3d6000fd5b50506003549150600090505b8181101561447857604080516001600160601b031960608e901b16602080830191909152603482018b90528c151560f81b60548301526055808301859052835180840390910181526075909201835281519181019190912060008181526006909252919020546001600160a01b031661446757604051636519c9d560e01b81526004810189905260248101889052604481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636519c9d590606401602060405180830381865afa1580156141f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061421c9190614e8e565b90506142998d306305f5e1007f0000000000000000000000000000000000000000000000000000000000000000614253868f614ed6565b61425d9190614ee9565b6142679190614f37565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169291906145ed565b6040518061016001604052808e6001600160a01b031681526020018d151581526020018c151581526020018b81526020018a8152602001898152602001828152602001888152602001878152602001868152602001428152506006600084815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160000160156101000a81548160ff021916908315150217905550606082015181600101556080820151816002015560a0820151816003015560c0820151816004015560e082015181600501556101008201518160060155610120820151816007015561014082015181600801559050508c6001600160a01b0316827fde124635deb0e2ebcbdd019f4c341021e58f79aafb89ae9949be65bc717cc30f8e8e8e8e8e888f8f8f426040516144569a999897969594939291909915158a5297151560208a015260408901969096526060880194909452608087019290925260a086015260c085015260e08401526101008301526101208201526101400190565b60405180910390a3505050506144cd565b5061447181614f1e565b905061410f565b5060405162461bcd60e51b8152602060048201526024808201527f4f726465724d616e616765723a206d61784f70656e4f726465727320657863656044820152631959195960e21b6064820152608401610a26565b505050505050505050565b6040516001600160a01b038316602482015260448101829052612c6690849063a9059cbb60e01b90606401613e5f565b600061455d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146259092919063ffffffff16565b805190915015612c66578080602001905181019061457b919061507b565b612c665760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a26565b6040516001600160a01b0380851660248301528316604482015260648101829052613ec39085906323b872dd60e01b90608401613e5f565b6060614634848460008561463c565b949350505050565b6060824710156146b45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a26565b6001600160a01b0385163b61470b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a26565b600080866001600160a01b031685876040516147279190615098565b60006040518083038185875af1925050503d8060008114614764576040519150601f19603f3d011682016040523d82523d6000602084013e614769565b606091505b5091509150614779828286614784565b979650505050505050565b606083156147935750816110c3565b8251156147a35782518084602001fd5b8160405162461bcd60e51b8152600401610a269190615048565b80356001600160a01b03811681146147d457600080fd5b919050565b6000806000606084860312156147ee57600080fd5b6147f7846147bd565b95602085013595506040909401359392505050565b600081518084526020808501945080840160005b8381101561483c57815187529582019590820190600101614820565b509495945050505050565b6000604080835261485a8184018661480c565b83810360208581019190915285518083528682019282019060005b8181101561490657845180516001600160a01b031684528481015115158585015286810151151587850152606080820151908501526080808201519085015260a0808201519085015260c0808201519085015260e080820151908501526101008082015190850152610120808201519085015261014090810151908401529383019361016090920191600101614875565b509098975050505050505050565b801515811461492257600080fd5b50565b60008060008060008060c0878903121561493e57600080fd5b614947876147bd565b9550602087013561495781614914565b9450604087013561496781614914565b959894975094956060810135955060808101359460a0909101359350915050565b60008060006060848603121561499d57600080fd5b6149a6846147bd565b92506020840135915060408401356149bd81614914565b809150509250925092565b6000602082840312156149da57600080fd5b5035919050565b600080604083850312156149f457600080fd5b50508035926020909101359150565b600080600080600080600060e0888a031215614a1e57600080fd5b873596506020880135614a3081614914565b9550604088013594506060880135614a4781614914565b93506080880135925060a0880135614a5e81614914565b8092505060c0880135905092959891949750929550565b600060208284031215614a8757600080fd5b6110c3826147bd565b60006040808352614aa38184018661480c565b83810360208581019190915285518083528682019282019060005b8181101561490657845180516001600160a01b031684528481015115158585015286810151151587850152606080820151908501526080808201519085015260a0808201519085015260c090810151908401529383019360e090920191600101614abe565b600080600080600080600080610100898b031215614b4057600080fd5b883597506020890135614b5281614914565b96506040890135614b6281614914565b979a96995096976060810135975060808101359660a0820135965060c0820135955060e0909101359350915050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715614bcd57614bcd614b91565b6040525050565b600067ffffffffffffffff821115614bee57614bee614b91565b5060051b60200190565b600082601f830112614c0957600080fd5b81356020614c1682614bd4565b604051614c238282614ba7565b83815260059390931b8501820192828101915086841115614c4357600080fd5b8286015b84811015614c5e5780358352918301918301614c47565b509695505050505050565b60008060008060808587031215614c7f57600080fd5b843567ffffffffffffffff80821115614c9757600080fd5b614ca388838901614bf8565b95506020870135915080821115614cb957600080fd5b614cc588838901614bf8565b94506040870135915080821115614cdb57600080fd5b614ce788838901614bf8565b93506060870135915080821115614cfd57600080fd5b50614d0a87828801614bf8565b91505092959194509250565b60008060008060808587031215614d2c57600080fd5b614d35856147bd565b9350602085013592506040850135614d4c81614914565b9396929550929360600135925050565b60008060408385031215614d6f57600080fd5b823567ffffffffffffffff80821115614d8757600080fd5b614d9386838701614bf8565b93506020850135915080821115614da957600080fd5b50614db685828601614bf8565b9150509250929050565b600080600080600060a08688031215614dd857600080fd5b8535614de381614914565b94506020860135614df381614914565b94979496505050506040830135926060810135926080909101359150565b60008060008060808587031215614e2757600080fd5b8435614e3281614914565b93506020850135614e4281614914565b93969395505050506040820135916060013590565b60008060408385031215614e6a57600080fd5b614e73836147bd565b91506020830135614e8381614914565b809150509250929050565b600060208284031215614ea057600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115614ed057614ed0614ea7565b92915050565b80820180821115614ed057614ed0614ea7565b6000816000190483118215151615614f0357614f03614ea7565b500290565b634e487b7160e01b600052603260045260246000fd5b600060018201614f3057614f30614ea7565b5060010190565b600082614f5457634e487b7160e01b600052601260045260246000fd5b500490565b604081526000614f6c604083018561480c565b82810360208401526133d0818561480c565b600060033d1115614f975760046000803e5060005160e01c5b90565b600060443d1015614fa85790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715614fd857505050505090565b8285019150815181811115614ff05750505050505090565b843d870101602082850101111561500a5750505050505090565b61501960208286010187614ba7565b509095945050505050565b60005b8381101561503f578181015183820152602001615027565b50506000910152565b6020815260008251806020840152615067816040850160208701615024565b601f01601f19169190910160400192915050565b60006020828403121561508d57600080fd5b81516110c381614914565b600082516150aa818460208701615024565b919091019291505056fea26469706673582212205632eb1c410cf1bc5b8f88ff870aea75a46d07a399d908b9cf9a5918513078a264736f6c634300081000330000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c000000000000000000000000137de6b9f0b91f4ede8ffecec41cd91341ae54720000000000000000000000002d6823fc318843265c3178c67a99c63acd0ec85b0000000000000000000000000000000000000000000000000de0b6b3a7640000
Deployed ByteCode
0x6080604052600436106102a05760003560e01c8063791b98bc1161016e578063c4d66de8116100cb578063e084f3581161007f578063ee0d84e211610064578063ee0d84e21461093a578063f3fadffb1461095a578063fa6165181461097a57600080fd5b8063e084f35814610870578063e57593131461091a57600080fd5b8063cb33d0be116100b0578063cb33d0be14610810578063cfad57a214610830578063d1b9e8531461085057600080fd5b8063c4d66de8146107d0578063c817b238146107f057600080fd5b80639af9255c11610122578063aae4b73411610107578063aae4b73414610769578063b2016bd414610789578063c0848ebe146107bd57600080fd5b80639af9255c146106d8578063a1f20fbf1461074957600080fd5b80637e7e3159116101535780637e7e3159146106525780638c4dc9d91461067257806390bb9e6a1461069257600080fd5b8063791b98bc146105fe5780637dc0d1d01461061e57600080fd5b806341e276e91161021c5780636962fe56116101d05780636f314266116101b55780636f3142661461059d57806373e15834146105cb57806375b77945146105eb57600080fd5b80636962fe561461055a5780636ba42aaa1461056d57600080fd5b806352a1c2a71161020157806352a1c2a71461042657806366cb458114610446578063692058c21461052657600080fd5b806341e276e9146103f05780634aa38c6d1461040657600080fd5b8063237aae9c1161027357806337a063d21161025857806337a063d214610399578063392e53cd146103b957806340e9903b146103da57600080fd5b8063237aae9c1461035557806336e5e4e21461037557600080fd5b806312d43a51146102a55780631683d218146102e25780631844f44f1461031057806320cd610414610325575b600080fd5b3480156102b157600080fd5b506001546102c5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102ee57600080fd5b506103026102fd3660046147d9565b6109d7565b6040516102d9929190614847565b61032361031e366004614925565b610f00565b005b34801561033157600080fd5b50610345610340366004614988565b611028565b60405190151581526020016102d9565b34801561036157600080fd5b506103236103703660046149c8565b6110ca565b34801561038157600080fd5b5061038b60045481565b6040519081526020016102d9565b3480156103a557600080fd5b506103236103b43660046149c8565b6115fe565b3480156103c557600080fd5b5060015461034590600160a01b900460ff1681565b3480156103e657600080fd5b5061038b60055481565b3480156103fc57600080fd5b5061038b60035481565b34801561041257600080fd5b506103236104213660046149c8565b61166a565b34801561043257600080fd5b506103236104413660046149e1565b6117e5565b34801561045257600080fd5b506104c36104613660046149c8565b60066020819052600091825260409091208054600182015460028301546003840154600485015460058601549686015460078701546008909701546001600160a01b0387169860ff600160a01b8904811699600160a81b90990416979092918b565b604080516001600160a01b03909c168c5299151560208c0152971515988a01989098526060890195909552608088019390935260a087019190915260c086015260e0850152610100840152610120830191909152610140820152610160016102d9565b34801561053257600080fd5b506102c57f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c81565b610323610568366004614a03565b6118a4565b34801561057957600080fd5b50610345610588366004614a75565b60086020526000908152604090205460ff1681565b3480156105a957600080fd5b506105bd6105b83660046147d9565b611ca6565b6040516102d9929190614a90565b3480156105d757600080fd5b5061038b6105e6366004614988565b61214a565b6103236105f9366004614b23565b6121ea565b34801561060a57600080fd5b506002546102c5906001600160a01b031681565b34801561062a57600080fd5b506102c57f000000000000000000000000137de6b9f0b91f4ede8ffecec41cd91341ae547281565b34801561065e57600080fd5b5061032361066d366004614c69565b6122f3565b34801561067e57600080fd5b5061032361068d3660046149c8565b6126fa565b34801561069e57600080fd5b506106b26106ad366004614d16565b612aed565b6040805194855260208501939093529015159183019190915260608201526080016102d9565b3480156106e457600080fd5b5061038b6106f3366004614d16565b6040516001600160601b0319606086901b1660208201526034810184905282151560f81b605482015260558101829052600090607501604051602081830303815290604052805190602001209050949350505050565b34801561075557600080fd5b50610323610764366004614d5c565b612be9565b34801561077557600080fd5b506103236107843660046149c8565b612c6b565b34801561079557600080fd5b506102c57f0000000000000000000000002d6823fc318843265c3178c67a99c63acd0ec85b81565b6103236107cb366004614dc0565b613060565b3480156107dc57600080fd5b506103236107eb366004614a75565b61312d565b3480156107fc57600080fd5b5061038b61080b366004614e11565b613241565b34801561081c57600080fd5b5061032361082b366004614988565b6133d9565b34801561083c57600080fd5b5061032361084b366004614a75565b6135ba565b34801561085c57600080fd5b5061032361086b366004614e57565b613663565b34801561087c57600080fd5b506108d561088b3660046149c8565b600760205260009081526040902080546001820154600283015460038401546004909401546001600160a01b0384169460ff600160a01b8604811695600160a81b90041693929187565b604080516001600160a01b0390981688529515156020880152931515948601949094526060850191909152608084015260a083019190915260c082015260e0016102d9565b34801561092657600080fd5b50610345610935366004614988565b613718565b34801561094657600080fd5b5061038b610955366004614988565b6137ac565b34801561096657600080fd5b506103236109753660046149e1565b613843565b34801561098657600080fd5b5061099a610995366004614d16565b61399c565b6040805198895260208901979097529587019490945260608601929092521515608085015260a084015260c083015260e0820152610100016102d9565b60608060008411610a2f5760405162461bcd60e51b815260206004820152601660248201527f4f726465724d616e616765723a2021737461727449640000000000000000000060448201526064015b60405180910390fd5b60007f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c6001600160a01b0316639b9d326d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab39190614e8e565b905080841115610ac1578093505b60035480610acf8787614ebd565b610ada906001614ed6565b610ae49190614ee9565b610aef906002614ee9565b67ffffffffffffffff811115610b0757610b07614b91565b604051908082528060200260200182016040528015610b30578160200160208202803683370190505b50935080610b3e8787614ebd565b610b49906001614ed6565b610b539190614ee9565b610b5e906002614ee9565b67ffffffffffffffff811115610b7657610b76614b91565b604051908082528060200260200182016040528015610c1157816020015b610bfe60405180610160016040528060006001600160a01b0316815260200160001515815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610b945790505b509250600080875b878111610ef35760005b84811015610ee2576040805160608d901b6001600160601b03191660208083019190915260348201859052600160f81b6054830152605580830185905283518084039091018152607590920190925280519101206000818152600660205260409020549094506001600160a01b031615610d805783888481518110610caa57610caa614f08565b6020908102919091018101919091526000858152600680835260409182902082516101608101845281546001600160a01b038116825260ff600160a01b82048116151596830196909652600160a81b90049094161515928401929092526001820154606084015260028201546080840152600382015460a0840152600482015460c0840152600582015460e08401528101546101008301526007810154610120830152600801546101408201528784610d6281614f1e565b955081518110610d7457610d74614f08565b60200260200101819052505b6040805160608d901b6001600160601b0319166020808301919091526034820185905260006054830152605580830185905283518084039091018152607590920190925280519101206000818152600660205260409020549094506001600160a01b031615610ed25783888481518110610dfc57610dfc614f08565b6020908102919091018101919091526000858152600680835260409182902082516101608101845281546001600160a01b038116825260ff600160a01b82048116151596830196909652600160a81b90049094161515928401929092526001820154606084015260028201546080840152600382015460a0840152600482015460c0840152600582015460e08401528101546101008301526007810154610120830152600801546101408201528784610eb481614f1e565b955081518110610ec657610ec6614f08565b60200260200101819052505b610edb81614f1e565b9050610c23565b50610eec81614f1e565b9050610c19565b5050505050935093915050565b600260005403610f525760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b60026000819055546001600160a01b03163314610fb15760405162461bcd60e51b815260206004820152601e60248201527f4f726465724d616e616765723a2021706f736974696f6e4d616e6167657200006044820152606401610a26565b600554341461100d5760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b61101b868686868686613ae2565b5050600160005550505050565b600454600090815b818110156110bc57604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600790915220546001600160a01b03166110ac576001925050506110c3565b6110b581614f1e565b9050611030565b5060009150505b9392505050565b333014806110e757503360009081526008602052604090205460ff165b6111335760405162461bcd60e51b815260206004820152601560248201527f4f726465724d616e616765723a20216b656570657200000000000000000000006044820152606401610a26565b60008181526006602081815260409283902083516101608101855281546001600160a01b03811680835260ff600160a01b83048116151595840195909552600160a81b9091049093161515948101949094526001810154606085015260028101546080850152600381015460a0850152600481015460c0850152600581015460e08501529182015461010084015260078201546101208401526008909101546101408301526111e0575050565b60006111fe826020015183604001518460e001518560600151613241565b90506112a37f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c6305f5e1007f0000000000000000000000000000000000000000000000000de0b6b3a76400008560c00151866080015161125e9190614ed6565b6112689190614ee9565b6112729190614f37565b6001600160a01b037f0000000000000000000000002d6823fc318843265c3178c67a99c63acd0ec85b169190613db1565b815160608301516020840151608085015160a0860151604051639267fbbd60e01b81526001600160a01b03958616600482015260248101949094529115156044840152606483015260848201527f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c90911690639267fbbd9060a401600060405180830381600087803b15801561133857600080fd5b505af115801561134c573d6000803e3d6000fd5b50505061010083015160019150156113b1576113a383600001518460200151856020015186606001516305f5e1008860a00151896080015161138e9190614ee9565b6113989190614f37565b886101000151613ae2565b6113ae600182614ed6565b90505b61012083015115611410576114028360000151846020015185602001511586606001516305f5e1008860a0015189608001516113ed9190614ee9565b6113f79190614f37565b886101200151613ae2565b61140d600182614ed6565b90505b60008481526006602081905260408220805475ffffffffffffffffffffffffffffffffffffffffffff1916815560018101839055600281018390556003810183905560048101839055600580820184905591810183905560078101839055600801829055543290611482908490614ee9565b604051600081818185875af1925050503d80600081146114be576040519150601f19603f3d011682016040523d82523d6000602084013e6114c3565b606091505b50509050806115275760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b83600001516001600160a01b0316857f07cc7aa86de748bd1ef6a42d07028c18d69cb3cf9556ff2d219aae37aa94350d86602001518760400151886060015189608001518a60a001518b60c001518c60e001518d61010001518e61012001518f61014001518f6040516115ef9b9a999897969594939291909a15158b5298151560208b015260408a01979097526060890195909552608088019390935260a087019190915260c086015260e08501526101008401526101208301526101408201526101600190565b60405180910390a35050505050565b6001546001600160a01b031633146116505760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b670de0b6b3a764000081111561166557600080fd5b600555565b6002600054036116bc5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b60026000908155818152600760205260409020546001600160a01b031633146117275760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b61173081613ec9565b60055460405160009133918381818185875af1925050503d8060008114611773576040519150601f19603f3d011682016040523d82523d6000602084013e611778565b606091505b50509050806117dc5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50506001600055565b6001546001600160a01b031633146118375760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b60056003541015801561184d5750600560045410155b6118995760405162461bcd60e51b815260206004820152601d60248201527f4f726465724d616e616765723a20216d61784e756d4f664f72646572730000006044820152606401610a26565b600391909155600455565b6002600054036118f65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b6002600090815587815260066020526040902080546001600160a01b031633146119625760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b861561197057600581018690555b60008515611a6d5781600601546000036119a457841561199f576006820185905561199c600282614ed6565b90505b611a6d565b84600003611a65576006820185905560055460405160009133918381818185875af1925050503d80600081146119f6576040519150601f19603f3d011682016040523d82523d6000602084013e6119fb565b606091505b5050905080611a5f5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50611a6d565b600682018590555b8315611b68578160070154600003611a9f578215611a9a5760078201839055611a97600282614ed6565b90505b611b68565b82600003611b60576007820183905560055460405160009133918381818185875af1925050503d8060008114611af1576040519150601f19603f3d011682016040523d82523d6000602084013e611af6565b606091505b5050905080611b5a5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50611b68565b600782018390555b8015611bd55780600554611b7c9190614ee9565b3414611bd55760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b4260088301819055825460018401546002850154600386015460048701546005880154600689015460078a01546040805160ff600160a01b8b04811615158252600160a81b8b041615156020820152908101979097526060870195909552608086019390935260a085019190915260c084015260e08301526101008201526101208101929092526001600160a01b0316908a907f0a5e00c5dd98a039848cc82972d5b769df4d9e8889c0d7dda308a38f7cdb18a9906101400160405180910390a35050600160005550505050505050565b60608060008411611cf95760405162461bcd60e51b815260206004820152601660248201527f4f726465724d616e616765723a202173746172744964000000000000000000006044820152606401610a26565b60007f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c6001600160a01b0316639b9d326d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d9190614e8e565b905080841115611d8b578093505b60045480611d998787614ebd565b611da4906001614ed6565b611dae9190614ee9565b611db9906002614ee9565b67ffffffffffffffff811115611dd157611dd1614b91565b604051908082528060200260200182016040528015611dfa578160200160208202803683370190505b50935080611e088787614ebd565b611e13906001614ed6565b611e1d9190614ee9565b611e28906002614ee9565b67ffffffffffffffff811115611e4057611e40614b91565b604051908082528060200260200182016040528015611ebe57816020015b611eab6040518060e0016040528060006001600160a01b03168152602001600015158152602001600015158152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081611e5e5790505b509250600080875b878111610ef35760005b84811015612139576040805160608d901b6001600160601b03191660208083019190915260348201859052600160f81b6054830152605580830185905283518084039091018152607590920190925280519101206000818152600760205260409020549094506001600160a01b0316156120025783888481518110611f5757611f57614f08565b602090810291909101810191909152600085815260078252604090819020815160e08101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b90049093161515918301919091526001810154606083015260028101546080830152600381015460a08301526004015460c08201528784611fe481614f1e565b955081518110611ff657611ff6614f08565b60200260200101819052505b6040805160608d901b6001600160601b0319166020808301919091526034820185905260006054830152605580830185905283518084039091018152607590920190925280519101206000818152600760205260409020549094506001600160a01b031615612129578388848151811061207e5761207e614f08565b602090810291909101810191909152600085815260078252604090819020815160e08101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b90049093161515918301919091526001810154606083015260028101546080830152600381015460a08301526004015460c0820152878461210b81614f1e565b95508151811061211d5761211d614f08565b60200260200101819052505b61213281614f1e565b9050611ed0565b5061214381614f1e565b9050611ec6565b600354600090815b818110156121e157604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600690915220546001600160a01b03166121d1576121ce600184614ed6565b92505b6121da81614f1e565b9050612152565b50509392505050565b60026000540361223c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b60026000556001821561225757612254600282614ed6565b90505b811561226b57612268600282614ed6565b90505b806005546122799190614ee9565b34146122d25760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b6122e33389898c8a8a8a8a8a614081565b5050600160005550505050505050565b3360009081526008602052604090205460ff166123525760405162461bcd60e51b815260206004820152601560248201527f4f726465724d616e616765723a20216b656570657200000000000000000000006044820152606401610a26565b604051630682f55760e51b81526001600160a01b037f000000000000000000000000137de6b9f0b91f4ede8ffecec41cd91341ae5472169063d05eaae0906123a09087908790600401614f59565b600060405180830381600087803b1580156123ba57600080fd5b505af11580156123ce573d6000803e3d6000fd5b5050505060005b825181101561256257306001600160a01b031663237aae9c8483815181106123ff576123ff614f08565b60200260200101516040518263ffffffff1660e01b815260040161242591815260200190565b600060405180830381600087803b15801561243f57600080fd5b505af1925050508015612450575060015b6125525761245c614f7e565b806308c379a00361251e5750612470614f9a565b8061247b5750612520565b6006600085848151811061249157612491614f08565b6020026020010151815260200190815260200160002060000160009054906101000a90046001600160a01b03166001600160a01b03168483815181106124d9576124d9614f08565b60200260200101517f81302fc3204662085acace33c36464c982ee6cd7aa54f729176650cc51a4b861836040516125109190615048565b60405180910390a350612552565b505b3d80801561254a576040519150601f19603f3d011682016040523d82523d6000602084013e61254f565b606091505b50505b61255b81614f1e565b90506123d5565b5060005b81518110156126f357306001600160a01b031663aae4b73483838151811061259057612590614f08565b60200260200101516040518263ffffffff1660e01b81526004016125b691815260200190565b600060405180830381600087803b1580156125d057600080fd5b505af19250505080156125e1575060015b6126e3576125ed614f7e565b806308c379a0036126af5750612601614f9a565b8061260c57506126b1565b6007600084848151811061262257612622614f08565b6020026020010151815260200190815260200160002060000160009054906101000a90046001600160a01b03166001600160a01b031683838151811061266a5761266a614f08565b60200260200101517f48b2b3f3b7cf047cbc676166e59b80a9aea26e67f2a964fcd4a5a945dec27a6f836040516126a19190615048565b60405180910390a3506126e3565b505b3d8080156126db576040519150601f19603f3d011682016040523d82523d6000602084013e6126e0565b606091505b50505b6126ec81614f1e565b9050612566565b5050505050565b60026000540361274c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b600260008181558281526006602081815260409283902083516101608101855281546001600160a01b03811680835260ff600160a01b83048116151595840195909552600160a81b90910490931615159481019490945260018101546060850152938401546080840152600384015460a0840152600484015460c0840152600584015460e08401529083015461010083015260078301546101208301526008909201546101408201529033146128445760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b6128c7336305f5e1007f0000000000000000000000000000000000000000000000000de0b6b3a76400008460c0015185608001516128829190614ed6565b61288c9190614ee9565b6128969190614f37565b6001600160a01b037f0000000000000000000000002d6823fc318843265c3178c67a99c63acd0ec85b1691906144d8565b60008281526006602081905260408220805475ffffffffffffffffffffffffffffffffffffffffffff1916815560018082018490556002820184905560038201849055600482018490556005820184905591810183905560078101839055600801919091556101008201511561294557612942600282614ed6565b90505b6101208201511561295e5761295b600282614ed6565b90505b6000336001600160a01b0316826005546129789190614ee9565b604051600081818185875af1925050503d80600081146129b4576040519150601f19603f3d011682016040523d82523d6000602084013e6129b9565b606091505b5050905080612a1d5760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b82600001516001600160a01b0316847f49358803a7ae36469d52afc763a7489ec58204d535ff56c6af7af33492244b4985602001518660400151876060015188608001518960a001518a60c001518b60e001518c61010001518d61012001518e6101400151604051612ada9a999897969594939291909915158a5297151560208a015260408901969096526060880194909452608087019290925260a086015260c085015260e08401526101008301526101208201526101400190565b60405180910390a3505060016000555050565b600080600080600060076000612b568b8b8b8b6040516001600160601b0319606086901b1660208201526034810184905282151560f81b605482015260558101829052600090607501604051602081830303815290604052805190602001209050949350505050565b81526020808201929092526040908101600020815160e08101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b9004909316151591830182905260018101546060840152600281015460808401819052600382015460a0850181905260049092015460c0909401849052975095509350915050945094509450949050565b60005b8251811015612c2757612c17838281518110612c0a57612c0a614f08565b60200260200101516126fa565b612c2081614f1e565b9050612bec565b5060005b8151811015612c6657612c56828281518110612c4957612c49614f08565b602002602001015161166a565b612c5f81614f1e565b9050612c2b565b505050565b33301480612c8857503360009081526008602052604090205460ff165b612cd45760405162461bcd60e51b815260206004820152601560248201527f4f726465724d616e616765723a20216b656570657200000000000000000000006044820152606401610a26565b600081815260076020908152604091829020825160e08101845281546001600160a01b03811680835260ff600160a01b83048116151595840195909552600160a81b9091049093161515938101939093526001810154606084015260028101546080840152600381015460a08401526004015460c0830152612d54575050565b6000612d7382602001511583604001518460a001518560600151613241565b6000848152600760209081526040808320805475ffffffffffffffffffffffffffffffffffffffffffff1916815560018101849055600281018490556003810184905560049081019390935585516060870151928701519151634df8059360e11b81526001600160a01b03808316958201959095526024810184905282151560448201529495507f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c909316936314d8353f939291908590639bf00b2690606401602060405180830381865afa158015612e50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e749190614e8e565b6305f5e1008860800151612e889190614ee9565b612e929190614f37565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b0390941660048501526024840192909252151560448301526064820152608401600060405180830381600087803b158015612eff57600080fd5b505af1158015612f13573d6000803e3d6000fd5b5050600554604051600093503292508381818185875af1925050503d8060008114612f5a576040519150601f19603f3d011682016040523d82523d6000602084013e612f5f565b606091505b5050905080612fc35760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b82600001516001600160a01b0316847f47036c05d3bcca301b675f2154fca0f55a59c635efd8b997a417d10b0c3ce1d185602001518660400151876060015188608001518960a001518a60c001518a60405161305297969594939291909615158752941515602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b60405180910390a350505050565b6002600054036130b25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b600260005560055434146131135760405162461bcd60e51b815260206004820152602260248201527f4f726465724d616e616765723a20696e76616c696420657865637574696f6e46604482015261656560f01b6064820152608401610a26565b613121338686868686613ae2565b50506001600055505050565b6001546001600160a01b0316331461317f5760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b600154600160a01b900460ff16156131e35760405162461bcd60e51b815260206004820152602160248201527f4f726465724d616e616765723a20616c726561647920696e697469616c697a656044820152601960fa1b6064820152608401610a26565b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055600280546001600160a01b0390921673ffffffffffffffffffffffffffffffffffffffff19909216919091179055565b604051632b82db0d60e11b815260048101829052841515602482015260009081906001600160a01b037f000000000000000000000000137de6b9f0b91f4ede8ffecec41cd91341ae54721690635705b61a90604401602060405180830381865afa1580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d79190614e8e565b9050841561335a57838110156133555760405162461bcd60e51b815260206004820152603260248201527f4f726465724d616e616765723a2063757272656e74207072696365206973206260448201527f656c6f77207472696767657220707269636500000000000000000000000000006064820152608401610a26565b6133d0565b838111156133d05760405162461bcd60e51b815260206004820152603260248201527f4f726465724d616e616765723a2063757272656e74207072696365206973206160448201527f626f7665207472696767657220707269636500000000000000000000000000006064820152608401610a26565b95945050505050565b336001600160a01b037f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c16146134515760405162461bcd60e51b815260206004820152601260248201527f4f726465724d616e616765723a202164657800000000000000000000000000006044820152606401610a26565b600454600090815b818110156134f557604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b60548301526055808301859052835180840390910181526075909201835281519181019190912060008181526007909252919020546001600160a01b0316156134e4576134d681613ec9565b6134e1600185614ed6565b93505b506134ee81614f1e565b9050613459565b5081156126f35760055460003261350c8584614ee9565b604051600081818185875af1925050503d8060008114613548576040519150601f19603f3d011682016040523d82523d6000602084013e61354d565b606091505b50509050806135b15760405162461bcd60e51b815260206004820152602a60248201527f4f726465724d616e616765723a206661696c656420746f2073656e6420657865604482015269637574696f6e2066656560b01b6064820152608401610a26565b50505050505050565b6001546001600160a01b0316331461360c5760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f91a8c1cc2d4a3bb60738481947a00cbb9899c822916694cf8bb1d68172fdcd5490600090a250565b6001546001600160a01b031633146136b55760405162461bcd60e51b815260206004820152601560248201527423b7bb32b93730b136329d103337b93134b23232b760591b6044820152606401610a26565b6001600160a01b038216600081815260086020908152604091829020805460ff19168515159081179091558251938452908301527f8c2ff6748f99f65f4ebf8a1e973a289bad216c4d5b20fda1940d9e01118ae42a910160405180910390a15050565b600354600090815b818110156110bc57604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600690915220546001600160a01b031661379c576001925050506110c3565b6137a581614f1e565b9050613720565b600454600090815b818110156121e157604080516001600160601b0319606089901b166020808301919091526034820188905286151560f81b6054830152605580830185905283518084039091018152607590920183528151918101919091206000908152600790915220546001600160a01b031661383357613830600184614ed6565b92505b61383c81614f1e565b90506137b4565b6002600054036138955760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a26565b6002600090815582815260076020526040902080546001600160a01b031633146139015760405162461bcd60e51b815260206004820152601c60248201527f4f726465724d616e616765723a20216f726465722e6163636f756e74000000006044820152606401610a26565b6003810182905542600482018190558154600183015460028401546040805160ff600160a01b8604811615158252600160a81b860416151560208201529081019290925260608201526080810185905260a08101929092526001600160a01b03169084907f6911fa079056e89ec24445683aa16240daff19f20221857b69ace7f7f2167f8a9060c00160405180910390a35050600160005550565b600080600080600080600080600060066000613a0b8f8f8f8f6040516001600160601b0319606086901b1660208201526034810184905282151560f81b605482015260558101829052600090607501604051602081830303815290604052805190602001209050949350505050565b8152602080820192909252604090810160002081516101608101835281546001600160a01b038116825260ff600160a01b82048116151595830195909552600160a81b9004909316151591830182905260018101546060840152600281015460808401819052600382015460a08501819052600483015460c08601819052600584015460e087018190526006850154610100880181905260078601546101208901819052600890960154610140909801889052939f50919d509b509950919750909550935091505094995094995094999196509450565b60008111613b585760405162461bcd60e51b815260206004820152602660248201527f4f726465724d616e616765723a207472696767657250726963652063616e6e6f60448201527f74206265203000000000000000000000000000000000000000000000000000006064820152608401610a26565b60045460005b81811015613d3a57604080516001600160601b031960608b901b166020808301919091526034820188905289151560f81b60548301526055808301859052835180840390910181526075909201835281519181019190912060008181526007909252919020546001600160a01b0316613d29576040805160e0810182526001600160a01b03808c168083528b151560208085019182528c1515858701908152606086018d8152608087018d815260a088018d81524260c08a0181815260008d81526007909752958b902099518a54975195511515600160a81b027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff961515600160a01b027fffffffffffffffffffffff00000000000000000000000000000000000000000090991691909a16179690961793909316969096178755516001870155935160028601559251600385015591516004909301929092559151909183917fd1d8633d045dfd8d52789d0505215f098a1777a0a0a8ac150c94a16d0231df1091613d19918d918d918d918d918d91909515158652931515602086015260408501929092526060840152608083015260a082015260c00190565b60405180910390a3505050613da9565b50613d3381614f1e565b9050613b5e565b5060405162461bcd60e51b815260206004820152602560248201527f4f726465724d616e616765723a206d6178436c6f73654f72646572732065786360448201527f65656465640000000000000000000000000000000000000000000000000000006064820152608401610a26565b505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015613e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e269190614e8e565b613e309190614ed6565b6040516001600160a01b038516602482015260448101829052909150613ec390859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614508565b50505050565b6000600760008381526020019081526020016000206040518060e00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900460ff161515151581526020016000820160159054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152602001600482015481525050905060076000838152602001908152602001600020600080820160006101000a8154906001600160a01b0302191690556000820160146101000a81549060ff02191690556000820160156101000a81549060ff02191690556001820160009055600282016000905560038201600090556004820160009055505080600001516001600160a01b0316827ff88686450cd096feaf4c9c73e01e80cc376845eac25202501d46a386ceef7cd583602001518460400151856060015186608001518760a001518860c00151604051614075969594939291909515158652931515602086015260408501929092526060840152608083015260a082015260c00190565b60405180910390a35050565b60405163021707f360e41b81526004810186905260248101859052604481018790527f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c6001600160a01b0316906321707f309060640160006040518083038186803b1580156140ef57600080fd5b505afa158015614103573d6000803e3d6000fd5b50506003549150600090505b8181101561447857604080516001600160601b031960608e901b16602080830191909152603482018b90528c151560f81b60548301526055808301859052835180840390910181526075909201835281519181019190912060008181526006909252919020546001600160a01b031661446757604051636519c9d560e01b81526004810189905260248101889052604481018a90526000907f0000000000000000000000009b6869733e4b2d1db6c1183dd7008136f6fa553c6001600160a01b031690636519c9d590606401602060405180830381865afa1580156141f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061421c9190614e8e565b90506142998d306305f5e1007f0000000000000000000000000000000000000000000000000de0b6b3a7640000614253868f614ed6565b61425d9190614ee9565b6142679190614f37565b6001600160a01b037f0000000000000000000000002d6823fc318843265c3178c67a99c63acd0ec85b169291906145ed565b6040518061016001604052808e6001600160a01b031681526020018d151581526020018c151581526020018b81526020018a8152602001898152602001828152602001888152602001878152602001868152602001428152506006600084815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160000160156101000a81548160ff021916908315150217905550606082015181600101556080820151816002015560a0820151816003015560c0820151816004015560e082015181600501556101008201518160060155610120820151816007015561014082015181600801559050508c6001600160a01b0316827fde124635deb0e2ebcbdd019f4c341021e58f79aafb89ae9949be65bc717cc30f8e8e8e8e8e888f8f8f426040516144569a999897969594939291909915158a5297151560208a015260408901969096526060880194909452608087019290925260a086015260c085015260e08401526101008301526101208201526101400190565b60405180910390a3505050506144cd565b5061447181614f1e565b905061410f565b5060405162461bcd60e51b8152602060048201526024808201527f4f726465724d616e616765723a206d61784f70656e4f726465727320657863656044820152631959195960e21b6064820152608401610a26565b505050505050505050565b6040516001600160a01b038316602482015260448101829052612c6690849063a9059cbb60e01b90606401613e5f565b600061455d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146259092919063ffffffff16565b805190915015612c66578080602001905181019061457b919061507b565b612c665760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a26565b6040516001600160a01b0380851660248301528316604482015260648101829052613ec39085906323b872dd60e01b90608401613e5f565b6060614634848460008561463c565b949350505050565b6060824710156146b45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a26565b6001600160a01b0385163b61470b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a26565b600080866001600160a01b031685876040516147279190615098565b60006040518083038185875af1925050503d8060008114614764576040519150601f19603f3d011682016040523d82523d6000602084013e614769565b606091505b5091509150614779828286614784565b979650505050505050565b606083156147935750816110c3565b8251156147a35782518084602001fd5b8160405162461bcd60e51b8152600401610a269190615048565b80356001600160a01b03811681146147d457600080fd5b919050565b6000806000606084860312156147ee57600080fd5b6147f7846147bd565b95602085013595506040909401359392505050565b600081518084526020808501945080840160005b8381101561483c57815187529582019590820190600101614820565b509495945050505050565b6000604080835261485a8184018661480c565b83810360208581019190915285518083528682019282019060005b8181101561490657845180516001600160a01b031684528481015115158585015286810151151587850152606080820151908501526080808201519085015260a0808201519085015260c0808201519085015260e080820151908501526101008082015190850152610120808201519085015261014090810151908401529383019361016090920191600101614875565b509098975050505050505050565b801515811461492257600080fd5b50565b60008060008060008060c0878903121561493e57600080fd5b614947876147bd565b9550602087013561495781614914565b9450604087013561496781614914565b959894975094956060810135955060808101359460a0909101359350915050565b60008060006060848603121561499d57600080fd5b6149a6846147bd565b92506020840135915060408401356149bd81614914565b809150509250925092565b6000602082840312156149da57600080fd5b5035919050565b600080604083850312156149f457600080fd5b50508035926020909101359150565b600080600080600080600060e0888a031215614a1e57600080fd5b873596506020880135614a3081614914565b9550604088013594506060880135614a4781614914565b93506080880135925060a0880135614a5e81614914565b8092505060c0880135905092959891949750929550565b600060208284031215614a8757600080fd5b6110c3826147bd565b60006040808352614aa38184018661480c565b83810360208581019190915285518083528682019282019060005b8181101561490657845180516001600160a01b031684528481015115158585015286810151151587850152606080820151908501526080808201519085015260a0808201519085015260c090810151908401529383019360e090920191600101614abe565b600080600080600080600080610100898b031215614b4057600080fd5b883597506020890135614b5281614914565b96506040890135614b6281614914565b979a96995096976060810135975060808101359660a0820135965060c0820135955060e0909101359350915050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715614bcd57614bcd614b91565b6040525050565b600067ffffffffffffffff821115614bee57614bee614b91565b5060051b60200190565b600082601f830112614c0957600080fd5b81356020614c1682614bd4565b604051614c238282614ba7565b83815260059390931b8501820192828101915086841115614c4357600080fd5b8286015b84811015614c5e5780358352918301918301614c47565b509695505050505050565b60008060008060808587031215614c7f57600080fd5b843567ffffffffffffffff80821115614c9757600080fd5b614ca388838901614bf8565b95506020870135915080821115614cb957600080fd5b614cc588838901614bf8565b94506040870135915080821115614cdb57600080fd5b614ce788838901614bf8565b93506060870135915080821115614cfd57600080fd5b50614d0a87828801614bf8565b91505092959194509250565b60008060008060808587031215614d2c57600080fd5b614d35856147bd565b9350602085013592506040850135614d4c81614914565b9396929550929360600135925050565b60008060408385031215614d6f57600080fd5b823567ffffffffffffffff80821115614d8757600080fd5b614d9386838701614bf8565b93506020850135915080821115614da957600080fd5b50614db685828601614bf8565b9150509250929050565b600080600080600060a08688031215614dd857600080fd5b8535614de381614914565b94506020860135614df381614914565b94979496505050506040830135926060810135926080909101359150565b60008060008060808587031215614e2757600080fd5b8435614e3281614914565b93506020850135614e4281614914565b93969395505050506040820135916060013590565b60008060408385031215614e6a57600080fd5b614e73836147bd565b91506020830135614e8381614914565b809150509250929050565b600060208284031215614ea057600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115614ed057614ed0614ea7565b92915050565b80820180821115614ed057614ed0614ea7565b6000816000190483118215151615614f0357614f03614ea7565b500290565b634e487b7160e01b600052603260045260246000fd5b600060018201614f3057614f30614ea7565b5060010190565b600082614f5457634e487b7160e01b600052601260045260246000fd5b500490565b604081526000614f6c604083018561480c565b82810360208401526133d0818561480c565b600060033d1115614f975760046000803e5060005160e01c5b90565b600060443d1015614fa85790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715614fd857505050505090565b8285019150815181811115614ff05750505050505090565b843d870101602082850101111561500a5750505050505090565b61501960208286010187614ba7565b509095945050505050565b60005b8381101561503f578181015183820152602001615027565b50506000910152565b6020815260008251806020840152615067816040850160208701615024565b601f01601f19169190910160400192915050565b60006020828403121561508d57600080fd5b81516110c381614914565b600082516150aa818460208701615024565b919091019291505056fea26469706673582212205632eb1c410cf1bc5b8f88ff870aea75a46d07a399d908b9cf9a5918513078a264736f6c63430008100033