false
true
0

Contract Address Details

0x8B5cCB7e0b77DbB2a1A701288Fe4351D4D067a2D

Contract Name
PositionRouter
Creator
0x64e7ff–1c04a3 at 0x2fce23–3e4277
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
90,594 Transactions
Transfers
0 Transfers
Gas Used
0
Last Balance Update
26041201
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
PositionRouter




Optimization enabled
true
Compiler version
v0.7.6+commit.7338295f




Optimization runs
200
EVM Version
istanbul




Verified at
2023-09-16T02:38:18.214758Z

Constructor Arguments

0x000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a27000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000a2a15d09519be00000

Arg [0] (address) : 0xb29ea150c870ea830d9890d94f326cb1b273ce8c
Arg [1] (address) : 0xa1077a294dde1b09bb078844df40758a5d0f9a27
Arg [2] (uint256) : 30
Arg [3] (uint256) : 3000000000000000000000

              

contracts/protocol/core/PositionRouter.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "../../dependencies/openzeppelin/contracts/SafeMath.sol";
import "../../dependencies/openzeppelin/contracts/SafeERC20.sol";
import "../../interfaces/IRouter.sol";
import "../../interfaces/IPositionRouter.sol";
import "./BasePositionManager.sol";

contract PositionRouter is BasePositionManager, IPositionRouter {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    struct IncreasePositionRequest {
        address account;
        address[] path;
        address indexToken;
        uint256 amountIn;
        uint256 minOut;
        uint256 sizeDelta;
        bool isLong;
        uint256 acceptablePrice;
        uint256 executionFee;
        uint256 blockNumber;
        uint256 blockTime;
        bool hasCollateralInETH;
    }

    struct DecreasePositionRequest {
        address account;
        address[] path;
        address indexToken;
        uint256 collateralDelta;
        uint256 sizeDelta;
        bool isLong;
        address receiver;
        uint256 acceptablePrice;
        uint256 minOut;
        uint256 executionFee;
        uint256 blockNumber;
        uint256 blockTime;
        bool withdrawETH;
    }

    uint256 public constant MAX_MIN_EXECUTION_FEE = 1e24;
    uint256 public constant MAX_MIN_BLOCK_DELAY_KEEPER = 10;
    uint256 public constant MAX_MAX_TIME_DELAY = 3600;

    uint256 public minExecutionFee;

    uint256 public minBlockDelayKeeper;
    uint256 public maxTimeDelay;

    bytes32[] public override increasePositionRequestKeys;
    bytes32[] public override decreasePositionRequestKeys;

    uint256 public override increasePositionRequestKeysStart;
    uint256 public override decreasePositionRequestKeysStart;

    mapping(address => bool) public isPositionKeeper;

    mapping(address => uint256) public increasePositionsIndex;
    mapping(bytes32 => IncreasePositionRequest) public increasePositionRequests;

    mapping(address => uint256) public decreasePositionsIndex;
    mapping(bytes32 => DecreasePositionRequest) public decreasePositionRequests;

    modifier onlyPositionKeeper() {
        require(
            isPositionKeeper[msg.sender],
            "PositionRouter: caller is not the position keeper"
        );
        _;
    }

    constructor(
        IAddressesProvider addressesProvider_,
        address _weth,
        uint256 _depositFee,
        uint256 _minExecutionFee
    ) BasePositionManager(addressesProvider_, _weth, _depositFee) {
        require(
            _minExecutionFee <= MAX_MIN_EXECUTION_FEE,
            "PositionRouter: minExecutionFee is too high"
        );
        minExecutionFee = _minExecutionFee;
        isPositionKeeper[address(this)] = true;
    }

    function setPositionKeeper(
        address _account,
        bool _isActive
    ) external onlyOwner {
        isPositionKeeper[_account] = _isActive;
        emit SetPositionKeeper(_account, _isActive);
    }

    function setMinExecutionFee(uint256 _minExecutionFee) external onlyOwner {
        require(
            _minExecutionFee <= MAX_MIN_EXECUTION_FEE,
            "PositionRouter: minExecutionFee is too high"
        );
        minExecutionFee = _minExecutionFee;
        emit SetMinExecutionFee(_minExecutionFee);
    }

    function setDelayValues(
        uint256 _minBlockDelayKeeper,
        uint256 _maxTimeDelay
    ) external onlyOwner {
        require(
            _minBlockDelayKeeper <= MAX_MIN_BLOCK_DELAY_KEEPER,
            "PositionRouter: minBlockDelayKeeper is too high"
        );
        require(
            _maxTimeDelay <= MAX_MAX_TIME_DELAY,
            "PositionRouter: maxTimeDelay is too high"
        );
        minBlockDelayKeeper = _minBlockDelayKeeper;
        maxTimeDelay = _maxTimeDelay;
        emit SetDelayValues(_minBlockDelayKeeper, _maxTimeDelay);
    }

    function setRequestKeysStartValues(
        uint256 _increasePositionRequestKeysStart,
        uint256 _decreasePositionRequestKeysStart
    ) external onlyOwner {
        require(
            _increasePositionRequestKeysStart <=
                increasePositionRequestKeys.length,
            "PositionRouter: increasePositionRequestKeysStart is too high"
        );
        require(
            _decreasePositionRequestKeysStart <=
                decreasePositionRequestKeys.length,
            "PositionRouter: decreasePositionRequestKeysStart is too high"
        );

        increasePositionRequestKeysStart = _increasePositionRequestKeysStart;
        decreasePositionRequestKeysStart = _decreasePositionRequestKeysStart;

        emit SetRequestKeysStartValues(
            _increasePositionRequestKeysStart,
            _decreasePositionRequestKeysStart
        );
    }

    function executeIncreasePositions(
        uint256 _endIndex,
        address payable _executionFeeReceiver
    ) external override onlyPositionKeeper {
        uint256 index = increasePositionRequestKeysStart;
        uint256 length = increasePositionRequestKeys.length;

        if (index >= length) {
            return;
        }

        if (_endIndex > length) {
            _endIndex = length;
        }

        while (index < _endIndex) {
            bytes32 key = increasePositionRequestKeys[index];

            // if the request was executed then delete the key from the array
            // if the request was not executed then break from the loop, this can happen if the
            // minimum number of blocks has not yet passed
            // an error could be thrown if the request is too old or if the slippage is
            // higher than what the user specified, or if there is insufficient liquidity for the position
            // in case an error was thrown, cancel the request
            try
                this.executeIncreasePosition(key, _executionFeeReceiver)
            returns (bool _wasExecuted) {
                if (!_wasExecuted) {
                    break;
                }
            } catch {
                // wrap this call in a try catch to prevent invalid cancels from blocking the loop
                try
                    this.cancelIncreasePosition(key, _executionFeeReceiver)
                returns (bool _wasCancelled) {
                    if (!_wasCancelled) {
                        break;
                    }
                } catch {}
            }

            delete increasePositionRequestKeys[index];
            index++;
        }

        increasePositionRequestKeysStart = index;
    }

    function executeDecreasePositions(
        uint256 _endIndex,
        address payable _executionFeeReceiver
    ) external override onlyPositionKeeper {
        uint256 index = decreasePositionRequestKeysStart;
        uint256 length = decreasePositionRequestKeys.length;

        if (index >= length) {
            return;
        }

        if (_endIndex > length) {
            _endIndex = length;
        }

        while (index < _endIndex) {
            bytes32 key = decreasePositionRequestKeys[index];

            // if the request was executed then delete the key from the array
            // if the request was not executed then break from the loop, this can happen if the
            // minimum number of blocks has not yet passed
            // an error could be thrown if the request is too old
            // in case an error was thrown, cancel the request
            try
                this.executeDecreasePosition(key, _executionFeeReceiver)
            returns (bool _wasExecuted) {
                if (!_wasExecuted) {
                    break;
                }
            } catch {
                // wrap this call in a try catch to prevent invalid cancels from blocking the loop
                try
                    this.cancelDecreasePosition(key, _executionFeeReceiver)
                returns (bool _wasCancelled) {
                    if (!_wasCancelled) {
                        break;
                    }
                } catch {}
            }

            delete decreasePositionRequestKeys[index];
            index++;
        }

        decreasePositionRequestKeysStart = index;
    }

    function createIncreasePosition(
        address[] memory _path,
        address _indexToken,
        uint256 _amountIn,
        uint256 _minOut,
        uint256 _sizeDelta,
        bool _isLong,
        uint256 _acceptablePrice,
        uint256 _executionFee
    ) external payable nonReentrant {
        require(
            _executionFee >= minExecutionFee,
            "PositionRouter: invalid executionFee"
        );
        require(
            msg.value == _executionFee,
            "PositionRouter: invalid msg.value"
        );
        require(
            _path.length == 1 || _path.length == 2,
            "PositionRouter: invalid _path length"
        );

        _transferInETH();

        if (_amountIn > 0) {
            IRouter(addressesProvider.getRouter()).pluginTransfer(
                _path[0],
                msg.sender,
                address(this),
                _amountIn
            );
        }

        _createIncreasePosition(
            msg.sender,
            _path,
            _indexToken,
            _amountIn,
            _minOut,
            _sizeDelta,
            _isLong,
            _acceptablePrice,
            _executionFee,
            false
        );
    }

    function createIncreasePositionETH(
        address[] memory _path,
        address _indexToken,
        uint256 _minOut,
        uint256 _sizeDelta,
        bool _isLong,
        uint256 _acceptablePrice,
        uint256 _executionFee
    ) external payable nonReentrant {
        require(
            _executionFee >= minExecutionFee,
            "PositionRouter: invalid executionFee"
        );
        require(
            msg.value >= _executionFee,
            "PositionRouter: invalid msg.value"
        );
        require(
            _path.length == 1 || _path.length == 2,
            "PositionRouter: invalid _path length"
        );
        require(_path[0] == weth, "PositionRouter: invalid _path");

        _transferInETH();

        uint256 amountIn = msg.value.sub(_executionFee);

        _createIncreasePosition(
            msg.sender,
            _path,
            _indexToken,
            amountIn,
            _minOut,
            _sizeDelta,
            _isLong,
            _acceptablePrice,
            _executionFee,
            true
        );
    }

    function createDecreasePosition(
        address[] memory _path,
        address _indexToken,
        uint256 _collateralDelta,
        uint256 _sizeDelta,
        bool _isLong,
        address _receiver,
        uint256 _acceptablePrice,
        uint256 _minOut,
        uint256 _executionFee,
        bool _withdrawETH
    ) external payable nonReentrant {
        require(
            _executionFee >= minExecutionFee,
            "PositionRouter: invalid executionFee"
        );
        require(
            msg.value == _executionFee,
            "PositionRouter: invalid msg.value"
        );
        require(
            _path.length == 1 || _path.length == 2,
            "PositionRouter: invalid _path length"
        );

        if (_withdrawETH) {
            require(
                _path[_path.length - 1] == weth,
                "PositionRouter: invalid _path"
            );
        }

        _transferInETH();

        _createDecreasePosition(
            msg.sender,
            _path,
            _indexToken,
            _collateralDelta,
            _sizeDelta,
            _isLong,
            _receiver,
            _acceptablePrice,
            _minOut,
            _executionFee,
            _withdrawETH
        );
    }

    function getRequestQueueLengths()
        external
        view
        returns (uint256, uint256, uint256, uint256)
    {
        return (
            increasePositionRequestKeysStart,
            increasePositionRequestKeys.length,
            decreasePositionRequestKeysStart,
            decreasePositionRequestKeys.length
        );
    }

    function executeIncreasePosition(
        bytes32 _key,
        address payable _executionFeeReceiver
    ) public nonReentrant returns (bool) {
        IncreasePositionRequest memory request = increasePositionRequests[_key];
        // if the request was already executed or cancelled, return true so that the executeIncreasePositions loop will continue executing the next request
        if (request.account == address(0)) {
            return true;
        }

        bool shouldExecute = _validateExecution(
            request.blockNumber,
            request.blockTime,
            request.account
        );
        if (!shouldExecute) {
            return false;
        }

        delete increasePositionRequests[_key];

        if (request.amountIn > 0) {
            uint256 amountIn = request.amountIn;

            address vault = addressesProvider.getVault();

            if (request.path.length > 1) {
                IERC20(request.path[0]).safeTransfer(vault, request.amountIn);
                amountIn = _swap(request.path, request.minOut, address(this));
            }

            uint256 afterFeeAmount = _collectFees(
                request.account,
                request.path,
                amountIn,
                request.indexToken,
                request.isLong,
                request.sizeDelta
            );
            IERC20(request.path[request.path.length - 1]).safeTransfer(
                vault,
                afterFeeAmount
            );
        }

        _increasePosition(
            request.account,
            request.path[request.path.length - 1],
            request.indexToken,
            request.sizeDelta,
            request.isLong,
            request.acceptablePrice
        );

        _transferOutETHWithGasLimitFallbackToWeth(
            request.executionFee,
            _executionFeeReceiver
        );

        emit ExecuteIncreasePosition(
            request.account,
            request.path,
            request.indexToken,
            request.amountIn,
            request.minOut,
            request.sizeDelta,
            request.isLong,
            request.acceptablePrice,
            request.executionFee,
            block.number.sub(request.blockNumber),
            block.timestamp.sub(request.blockTime)
        );

        return true;
    }

    function cancelIncreasePosition(
        bytes32 _key,
        address payable _executionFeeReceiver
    ) public nonReentrant returns (bool) {
        IncreasePositionRequest memory request = increasePositionRequests[_key];
        // if the request was already executed or cancelled, return true so that the executeIncreasePositions loop will continue executing the next request
        if (request.account == address(0)) {
            return true;
        }

        bool shouldCancel = _validateCancellation(
            request.blockNumber,
            request.blockTime,
            request.account
        );
        if (!shouldCancel) {
            return false;
        }

        delete increasePositionRequests[_key];

        if (request.hasCollateralInETH) {
            _transferOutETHWithGasLimitFallbackToWeth(
                request.amountIn,
                payable(request.account)
            );
        } else {
            IERC20(request.path[0]).safeTransfer(
                request.account,
                request.amountIn
            );
        }

        _transferOutETHWithGasLimitFallbackToWeth(
            request.executionFee,
            _executionFeeReceiver
        );

        emit CancelIncreasePosition(
            request.account,
            request.path,
            request.indexToken,
            request.amountIn,
            request.minOut,
            request.sizeDelta,
            request.isLong,
            request.acceptablePrice,
            request.executionFee,
            block.number.sub(request.blockNumber),
            block.timestamp.sub(request.blockTime)
        );

        return true;
    }

    function executeDecreasePosition(
        bytes32 _key,
        address payable _executionFeeReceiver
    ) public nonReentrant returns (bool) {
        DecreasePositionRequest memory request = decreasePositionRequests[_key];
        // if the request was already executed or cancelled, return true so that the executeDecreasePositions loop will continue executing the next request
        if (request.account == address(0)) {
            return true;
        }

        bool shouldExecute = _validateExecution(
            request.blockNumber,
            request.blockTime,
            request.account
        );
        if (!shouldExecute) {
            return false;
        }

        delete decreasePositionRequests[_key];

        uint256 amountOut = _decreasePosition(
            request.account,
            request.path[0],
            request.indexToken,
            request.collateralDelta,
            request.sizeDelta,
            request.isLong,
            address(this),
            request.acceptablePrice
        );

        if (amountOut > 0) {
            if (request.path.length > 1) {
                IERC20(request.path[0]).safeTransfer(
                    addressesProvider.getVault(),
                    amountOut
                );
                amountOut = _swap(request.path, request.minOut, address(this));
            }

            if (request.withdrawETH) {
                _transferOutETHWithGasLimitFallbackToWeth(
                    amountOut,
                    payable(request.receiver)
                );
            } else {
                IERC20(request.path[request.path.length - 1]).safeTransfer(
                    request.receiver,
                    amountOut
                );
            }
        }

        _transferOutETHWithGasLimitFallbackToWeth(
            request.executionFee,
            _executionFeeReceiver
        );

        emit ExecuteDecreasePosition(
            request.account,
            request.path,
            request.indexToken,
            request.collateralDelta,
            request.sizeDelta,
            request.isLong,
            request.receiver,
            request.acceptablePrice,
            request.minOut,
            request.executionFee,
            block.number.sub(request.blockNumber),
            block.timestamp.sub(request.blockTime)
        );

        return true;
    }

    function cancelDecreasePosition(
        bytes32 _key,
        address payable _executionFeeReceiver
    ) public nonReentrant returns (bool) {
        DecreasePositionRequest memory request = decreasePositionRequests[_key];
        // if the request was already executed or cancelled, return true so that the executeDecreasePositions loop will continue executing the next request
        if (request.account == address(0)) {
            return true;
        }

        bool shouldCancel = _validateCancellation(
            request.blockNumber,
            request.blockTime,
            request.account
        );
        if (!shouldCancel) {
            return false;
        }

        delete decreasePositionRequests[_key];

        _transferOutETHWithGasLimitFallbackToWeth(
            request.executionFee,
            _executionFeeReceiver
        );

        emit CancelDecreasePosition(
            request.account,
            request.path,
            request.indexToken,
            request.collateralDelta,
            request.sizeDelta,
            request.isLong,
            request.receiver,
            request.acceptablePrice,
            request.minOut,
            request.executionFee,
            block.number.sub(request.blockNumber),
            block.timestamp.sub(request.blockTime)
        );

        return true;
    }

    function getRequestKey(
        address _account,
        uint256 _index
    ) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(_account, _index));
    }

    function getIncreasePositionRequestPath(
        bytes32 _key
    ) public view returns (address[] memory) {
        IncreasePositionRequest memory request = increasePositionRequests[_key];
        return request.path;
    }

    function getDecreasePositionRequestPath(
        bytes32 _key
    ) public view returns (address[] memory) {
        DecreasePositionRequest memory request = decreasePositionRequests[_key];
        return request.path;
    }

    function _validateExecution(
        uint256 _positionBlockNumber,
        uint256 _positionBlockTime,
        address _account
    ) internal view returns (bool) {
        require(
            block.timestamp < _positionBlockTime.add(maxTimeDelay),
            "PositionRouter: request has expired"
        );

        return
            _validateCancellation(
                _positionBlockNumber,
                _positionBlockTime,
                _account
            );
    }

    function _validateCancellation(
        uint256 _positionBlockNumber,
        uint256 _positionBlockTime,
        address _account
    ) internal view returns (bool) {
        if (isPositionKeeper[msg.sender]) {
            return
                _positionBlockNumber.add(minBlockDelayKeeper) <= block.number;
        }

        require(
            msg.sender == _account &&
                _positionBlockTime.add(minTimeDelayPublic) <= block.timestamp,
            "PositionRouter: forbidden"
        );
        return true;
    }

    function _createIncreasePosition(
        address _account,
        address[] memory _path,
        address _indexToken,
        uint256 _amountIn,
        uint256 _minOut,
        uint256 _sizeDelta,
        bool _isLong,
        uint256 _acceptablePrice,
        uint256 _executionFee,
        bool _hasCollateralInETH
    ) internal {
        uint256 index = increasePositionsIndex[_account].add(1);
        increasePositionsIndex[_account] = index;

        IncreasePositionRequest memory request = IncreasePositionRequest(
            _account,
            _path,
            _indexToken,
            _amountIn,
            _minOut,
            _sizeDelta,
            _isLong,
            _acceptablePrice,
            _executionFee,
            block.number,
            block.timestamp,
            _hasCollateralInETH
        );

        bytes32 key = getRequestKey(_account, index);
        increasePositionRequests[key] = request;

        increasePositionRequestKeys.push(key);

        emit CreateIncreasePosition(
            _account,
            _path,
            _indexToken,
            _amountIn,
            _minOut,
            _sizeDelta,
            _isLong,
            _acceptablePrice,
            _executionFee,
            index,
            block.number,
            block.timestamp,
            tx.gasprice
        );
    }

    function _createDecreasePosition(
        address _account,
        address[] memory _path,
        address _indexToken,
        uint256 _collateralDelta,
        uint256 _sizeDelta,
        bool _isLong,
        address _receiver,
        uint256 _acceptablePrice,
        uint256 _minOut,
        uint256 _executionFee,
        bool _withdrawETH
    ) internal {
        uint256 index = decreasePositionsIndex[_account].add(1);
        decreasePositionsIndex[_account] = index;

        DecreasePositionRequest memory request = DecreasePositionRequest(
            _account,
            _path,
            _indexToken,
            _collateralDelta,
            _sizeDelta,
            _isLong,
            _receiver,
            _acceptablePrice,
            _minOut,
            _executionFee,
            block.number,
            block.timestamp,
            _withdrawETH
        );

        bytes32 key = getRequestKey(_account, index);
        decreasePositionRequests[key] = request;

        decreasePositionRequestKeys.push(key);

        emit CreateDecreasePosition(
            _account,
            _path,
            _indexToken,
            _collateralDelta,
            _sizeDelta,
            _isLong,
            _receiver,
            _acceptablePrice,
            _minOut,
            _executionFee,
            index,
            block.number,
            block.timestamp
        );
    }
}
        

contracts/dependencies/openzeppelin/contracts/Address.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(
            address(this).balance >= amount,
            "Address: insufficient balance"
        );

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{value: amount}("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                value,
                "Address: low-level call with value failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(
            address(this).balance >= value,
            "Address: insufficient balance for call"
        );
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{value: value}(
            data
        );
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data)
        internal
        view
        returns (bytes memory)
    {
        return
            functionStaticCall(
                target,
                data,
                "Address: low-level static call failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return
            functionDelegateCall(
                target,
                data,
                "Address: low-level delegate call failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) private pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}
          

contracts/dependencies/openzeppelin/contracts/Context.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}
          

contracts/dependencies/openzeppelin/contracts/IERC20.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}
          

contracts/dependencies/openzeppelin/contracts/Ownable.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(
            newOwner != address(0),
            "Ownable: new owner is the zero address"
        );
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}
          

contracts/dependencies/openzeppelin/contracts/ReentrancyGuard.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

/**
 * @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 make 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;
    }
}
          

contracts/dependencies/openzeppelin/contracts/SafeERC20.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC20.sol";
import "./SafeMath.sol";
import "./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 SafeMath for uint256;
    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'
        // solhint-disable-next-line max-line-length
        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).add(
            value
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                newAllowance
            )
        );
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(
            value,
            "SafeERC20: decreased allowance below zero"
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                newAllowance
            )
        );
    }

    /**
     * @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
            // solhint-disable-next-line max-line-length
            require(
                abi.decode(returndata, (bool)),
                "SafeERC20: ERC20 operation did not succeed"
            );
        }
    }
}
          

contracts/dependencies/openzeppelin/contracts/SafeMath.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b)
        internal
        pure
        returns (bool, uint256)
    {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b)
        internal
        pure
        returns (bool, uint256)
    {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b)
        internal
        pure
        returns (bool, uint256)
    {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b)
        internal
        pure
        returns (bool, uint256)
    {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b)
        internal
        pure
        returns (bool, uint256)
    {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}
          

contracts/interfaces/IAddressesProvider.sol

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;

interface IAddressesProvider {
    function getUsdph() external view returns (address);

    function getPhlp() external view returns (address);

    function getPhlpManager() external view returns (address);

    function getVault() external view returns (address);

    function getVaultConfigurator() external view returns (address);

    function getRouter() external view returns (address);

    function getOrderBook() external view returns (address);

    function getPositionManager() external view returns (address);

    function getPositionRouter() external view returns (address);

    function getPriceOracle() external view returns (address);

    function getShortsTracker() external view returns (address);

    function getTreasury() external view returns (address payable);
}
          

contracts/interfaces/IBasePositionManager.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IBasePositionManager {
    event SetDepositFee(uint256 depositFee);
    event SetEthTransferGasLimit(uint256 ethTransferGasLimit);
    event SetMinTimeDelayPublic(uint256 minTimeDelayPublic);
    event SetIncreasePositionBufferBps(uint256 increasePositionBufferBps);
    event WithdrawFees(address token, address receiver, uint256 amount);

    event SetMaxGlobalSizes(
        address[] tokens,
        uint256[] longSizes,
        uint256[] shortSizes
    );

    function maxGlobalLongSizes(address _token) external view returns (uint256);

    function maxGlobalShortSizes(
        address _token
    ) external view returns (uint256);

    function withdrawFees(address _token, address _receiver) external;
}
          

contracts/interfaces/IPhamePriceOracle.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IPhamePriceOracle {
    function backupPriceOracle() external view returns (address);

    function adjustmentBps(address _token) external view returns (uint256);

    function isAdjustmentAdditive(address _token) external view returns (bool);

    function setAdjustment(
        address _token,
        bool _isAdditive,
        uint256 _adjustmentBps
    ) external;

    function setSpreadBps(address _token, uint256 _spreadBps) external;

    function setSpreadThresholdBps(uint256 _spreadThresholdBps) external;

    function setPriceSampleSpace(uint256 _priceSampleSpace) external;

    function setMaxStrictPriceDeviation(
        uint256 _maxStrictPriceDeviation
    ) external;

    function getPrice(
        address _token,
        bool _maximise
    ) external view returns (uint256);

    function setTokenConfig(
        address _token,
        address _priceFeed,
        uint256 _priceDecimals,
        bool _isStrictStable
    ) external;
}
          

contracts/interfaces/IPositionRouter.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IPositionRouter {
    event CreateIncreasePosition(
        address indexed account,
        address[] path,
        address indexToken,
        uint256 amountIn,
        uint256 minOut,
        uint256 sizeDelta,
        bool isLong,
        uint256 acceptablePrice,
        uint256 executionFee,
        uint256 index,
        uint256 blockNumber,
        uint256 blockTime,
        uint256 gasPrice
    );

    event ExecuteIncreasePosition(
        address indexed account,
        address[] path,
        address indexToken,
        uint256 amountIn,
        uint256 minOut,
        uint256 sizeDelta,
        bool isLong,
        uint256 acceptablePrice,
        uint256 executionFee,
        uint256 blockGap,
        uint256 timeGap
    );

    event CancelIncreasePosition(
        address indexed account,
        address[] path,
        address indexToken,
        uint256 amountIn,
        uint256 minOut,
        uint256 sizeDelta,
        bool isLong,
        uint256 acceptablePrice,
        uint256 executionFee,
        uint256 blockGap,
        uint256 timeGap
    );

    event CreateDecreasePosition(
        address indexed account,
        address[] path,
        address indexToken,
        uint256 collateralDelta,
        uint256 sizeDelta,
        bool isLong,
        address receiver,
        uint256 acceptablePrice,
        uint256 minOut,
        uint256 executionFee,
        uint256 index,
        uint256 blockNumber,
        uint256 blockTime
    );

    event ExecuteDecreasePosition(
        address indexed account,
        address[] path,
        address indexToken,
        uint256 collateralDelta,
        uint256 sizeDelta,
        bool isLong,
        address receiver,
        uint256 acceptablePrice,
        uint256 minOut,
        uint256 executionFee,
        uint256 blockGap,
        uint256 timeGap
    );

    event CancelDecreasePosition(
        address indexed account,
        address[] path,
        address indexToken,
        uint256 collateralDelta,
        uint256 sizeDelta,
        bool isLong,
        address receiver,
        uint256 acceptablePrice,
        uint256 minOut,
        uint256 executionFee,
        uint256 blockGap,
        uint256 timeGap
    );

    event SetPositionKeeper(address indexed account, bool isActive);
    event SetMinExecutionFee(uint256 minExecutionFee);
    event SetIsLeverageEnabled(bool isLeverageEnabled);
    event SetDelayValues(uint256 minBlockDelayKeeper, uint256 maxTimeDelay);
    event SetRequestKeysStartValues(
        uint256 increasePositionRequestKeysStart,
        uint256 decreasePositionRequestKeysStart
    );

    function increasePositionRequestKeys(
        uint256 idx
    ) external view returns (bytes32);

    function decreasePositionRequestKeys(
        uint256 idx
    ) external view returns (bytes32);

    function increasePositionRequestKeysStart() external view returns (uint256);

    function decreasePositionRequestKeysStart() external view returns (uint256);

    function executeIncreasePositions(
        uint256 _count,
        address payable _executionFeeReceiver
    ) external;

    function executeDecreasePositions(
        uint256 _count,
        address payable _executionFeeReceiver
    ) external;
}
          

contracts/interfaces/IRouter.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IRouter {
    event Swap(
        address account,
        address tokenIn,
        address tokenOut,
        uint256 amountIn,
        uint256 amountOut
    );

    function pluginTransfer(
        address _token,
        address _account,
        address _receiver,
        uint256 _amount
    ) external;

    function pluginIncreasePosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        uint256 _sizeDelta,
        bool _isLong
    ) external;

    function pluginDecreasePosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        uint256 _collateralDelta,
        uint256 _sizeDelta,
        bool _isLong,
        address _receiver
    ) external returns (uint256);

    function swap(
        address[] memory _path,
        uint256 _amountIn,
        uint256 _minOut,
        address _receiver
    ) external;
}
          

contracts/interfaces/IShortsTracker.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IShortsTracker {
    function globalShortAveragePrices(
        address _token
    ) external view returns (uint256);

    function getNextGlobalShortData(
        address _account,
        address _collateralToken,
        address _indexToken,
        uint256 _nextPrice,
        uint256 _sizeDelta,
        bool _isIncrease
    ) external view returns (uint256, uint256);

    function updateGlobalShortData(
        address _account,
        address _collateralToken,
        address _indexToken,
        bool _isLong,
        uint256 _sizeDelta,
        uint256 _markPrice,
        bool _isIncrease
    ) external;
}
          

contracts/interfaces/IVault.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;

import "../protocol/libraries/types/DataTypes.sol";
import "./IAddressesProvider.sol";

interface IVault {
    struct Position {
        uint256 size;
        uint256 collateral;
        uint256 averagePrice;
        uint256 entryFundingRate;
        uint256 reserveAmount;
        int256 realisedPnl;
        uint256 lastIncreasedTime;
    }

    event BuyUSDPH(
        address account,
        address token,
        uint256 tokenAmount,
        uint256 usdphAmount,
        uint256 feeBps
    );
    event SellUSDPH(
        address account,
        address token,
        uint256 usdphAmount,
        uint256 tokenAmount,
        uint256 feeBps
    );
    event Swap(
        address account,
        address tokenIn,
        address tokenOut,
        uint256 amountIn,
        uint256 amountOut,
        uint256 amountOutAfterFees,
        uint256 feeBps
    );
    event IncreasePosition(
        bytes32 key,
        address account,
        address collateralToken,
        address indexToken,
        uint256 collateralDelta,
        uint256 sizeDelta,
        bool isLong,
        uint256 price,
        uint256 fee
    );
    event DecreasePosition(
        bytes32 key,
        address account,
        address collateralToken,
        address indexToken,
        uint256 collateralDelta,
        uint256 sizeDelta,
        bool isLong,
        uint256 price,
        uint256 fee
    );
    event LiquidatePosition(
        bytes32 key,
        address account,
        address collateralToken,
        address indexToken,
        bool isLong,
        uint256 size,
        uint256 collateral,
        uint256 reserveAmount,
        int256 realisedPnl,
        uint256 markPrice
    );
    event UpdatePosition(
        bytes32 key,
        uint256 size,
        uint256 collateral,
        uint256 averagePrice,
        uint256 entryFundingRate,
        uint256 reserveAmount,
        int256 realisedPnl,
        uint256 markPrice
    );
    event ClosePosition(
        bytes32 key,
        uint256 size,
        uint256 collateral,
        uint256 averagePrice,
        uint256 entryFundingRate,
        uint256 reserveAmount,
        int256 realisedPnl
    );

    event UpdateFundingRate(address token, uint256 fundingRate);
    event UpdatePnl(bytes32 key, bool hasProfit, uint256 delta);

    event CollectSwapFees(address token, uint256 feeUsd, uint256 feeTokens);
    event CollectMarginFees(address token, uint256 feeUsd, uint256 feeTokens);
    event PayLpFees(address token, uint256 feeTokens);

    event DirectPoolDeposit(address token, uint256 amount);
    event IncreasePoolAmount(address token, uint256 amount);
    event DecreasePoolAmount(address token, uint256 amount);
    event IncreaseUsdphAmount(address token, uint256 amount);
    event DecreaseUsdphAmount(address token, uint256 amount);
    event IncreaseReservedAmount(address token, uint256 amount);
    event DecreaseReservedAmount(address token, uint256 amount);
    event IncreaseGuaranteedUsd(address token, uint256 amount);
    event DecreaseGuaranteedUsd(address token, uint256 amount);

    function addressesProvider() external view returns (IAddressesProvider);

    function getVaultConfig()
        external
        view
        returns (DataTypes.VaultConfig memory);

    function setVaultConfig(
        DataTypes.VaultConfig calldata vaultConfig
    ) external;

    function allWhitelistedTokensLength() external view returns (uint256);

    function totalTokenWeights() external view returns (uint256);

    function allWhitelistedTokens(uint256) external view returns (address);

    function getTokenConfig(
        address _token
    ) external view returns (DataTypes.TokenConfig memory);

    function setTokenConfig(
        address _token,
        DataTypes.TokenConfig calldata tokenConfig
    ) external;

    function clearTokenConfig(address _token) external;

    function setUsdphAmount(address _token, uint256 _amount) external;

    function tokenBalances(address _token) external view returns (uint256);

    function lastFundingTimes(address _token) external view returns (uint256);

    function withdrawFees(
        address _token,
        address _receiver
    ) external returns (uint256);

    function directPoolDeposit(address _token) external;

    function buyUSDPH(
        address _token,
        address _receiver
    ) external returns (uint256);

    function buyUSDPHwithoutFee(address _token) external returns (uint256);

    function sellUSDPH(
        address _token,
        address _receiver
    ) external returns (uint256);

    function swap(
        address _tokenIn,
        address _tokenOut,
        address _receiver
    ) external returns (uint256);

    function increasePosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        uint256 _sizeDelta,
        bool _isLong
    ) external;

    function decreasePosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        uint256 _collateralDelta,
        uint256 _sizeDelta,
        bool _isLong,
        address _receiver
    ) external returns (uint256);

    function validateLiquidation(
        address _account,
        address _collateralToken,
        address _indexToken,
        bool _isLong,
        bool _raise
    ) external view returns (uint256, uint256);

    function liquidatePosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        bool _isLong,
        address _feeReceiver
    ) external;

    function tokenToUsdMin(
        address _token,
        uint256 _tokenAmount
    ) external view returns (uint256);

    function cumulativeFundingRates(
        address _token
    ) external view returns (uint256);

    function getNextFundingRate(address _token) external view returns (uint256);

    function getFeeBps(
        address _token,
        uint256 _usdphDelta,
        uint256 _feeBps,
        uint256 _taxBps,
        bool _increment
    ) external view returns (uint256);

    function feeReserves(address _token) external view returns (uint256);

    function globalShortSizes(address _token) external view returns (uint256);

    function guaranteedUsd(address _token) external view returns (uint256);

    function poolAmounts(address _token) external view returns (uint256);

    function reservedAmounts(address _token) external view returns (uint256);

    function usdphAmounts(address _token) external view returns (uint256);

    function getRedemptionAmount(
        address _token,
        uint256 _usdphAmount
    ) external view returns (uint256);

    function getDelta(
        address _indexToken,
        uint256 _size,
        uint256 _averagePrice,
        bool _isLong,
        uint256 _lastIncreasedTime
    ) external view returns (bool, uint256);

    function getPosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        bool _isLong
    )
        external
        view
        returns (
            uint256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256,
            bool,
            uint256
        );
}
          

contracts/interfaces/IVaultConfigurator.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;

interface IVaultConfigurator {
    function setIsLeverageEnabled(bool _isLeverageEnabled) external;

    function setStakingBps(uint256 _stakingBps) external;

    function setUsdphAmount(address _token, uint256 _amount) external;

    function getSwapFeeAndTaxBps(
        bool isStableSwap
    ) external view returns (uint256, uint256);
}
          

contracts/interfaces/IWETH.sol

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;

interface IWETH {
    function deposit() external payable;

    function withdraw(uint256) external;

    function approve(address guy, uint256 wad) external returns (bool);

    function transfer(address to, uint value) external returns (bool);

    function transferFrom(
        address src,
        address dst,
        uint256 wad
    ) external returns (bool);
}
          

contracts/protocol/core/BasePositionManager.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

import "../../dependencies/openzeppelin/contracts/Ownable.sol";
import "../../dependencies/openzeppelin/contracts/SafeMath.sol";
import "../../dependencies/openzeppelin/contracts/Address.sol";
import "../../dependencies/openzeppelin/contracts/ReentrancyGuard.sol";
import "../../dependencies/openzeppelin/contracts/IERC20.sol";
import "../../dependencies/openzeppelin/contracts/SafeERC20.sol";
import "../../interfaces/IAddressesProvider.sol";
import "../../interfaces/IPhamePriceOracle.sol";
import "../../interfaces/IWETH.sol";
import "../../interfaces/IRouter.sol";
import "../../interfaces/IVault.sol";
import "../../interfaces/IVaultConfigurator.sol";
import "../../interfaces/IShortsTracker.sol";
import "../../interfaces/IBasePositionManager.sol";

contract BasePositionManager is IBasePositionManager, ReentrancyGuard, Ownable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    using Address for address payable;

    uint256 public constant MAX_MIN_TIME_DELAY_PUBLIC = 600;
    uint256 public constant BASIS_POINTS_DIVISOR = 10000;
    uint256 public constant MAX_DEPOSIT_FEE = 100;
    uint256 public constant MAX_INCREASE_POSITION_BUFFER_BPS = 10000;

    IAddressesProvider public immutable addressesProvider;
    address public immutable weth;

    uint256 public ethTransferGasLimit = 500 * 1000;
    uint256 public minTimeDelayPublic;
    // to prevent using the deposit and withdrawal of collateral as a zero fee swap,
    // there is a small depositFee charged if a collateral deposit results in the decrease
    // of leverage for an existing position
    // increasePositionBufferBps allows for a small amount of decrease of leverage
    uint256 public depositFee;
    uint256 public increasePositionBufferBps = 100;

    mapping(address => uint256) public feeReserves;

    mapping(address => uint256) public override maxGlobalLongSizes;
    mapping(address => uint256) public override maxGlobalShortSizes;

    constructor(
        IAddressesProvider addressesProvider_,
        address _weth,
        uint256 _depositFee
    ) Ownable() {
        require(
            address(addressesProvider_) != address(0),
            "BasePositionManager: addressesProvider is zero address"
        );
        require(
            _weth != address(0),
            "BasePositionManager: weth is zero address"
        );
        require(
            _depositFee <= MAX_DEPOSIT_FEE,
            "BasePositionManager: depositFee is too high"
        );
        addressesProvider = addressesProvider_;
        weth = _weth;
        depositFee = _depositFee;
    }

    receive() external payable {
        require(msg.sender == weth, "BasePositionManager: invalid sender");
    }

    function setEthTransferGasLimit(
        uint256 _ethTransferGasLimit
    ) external onlyOwner {
        ethTransferGasLimit = _ethTransferGasLimit;
        emit SetEthTransferGasLimit(_ethTransferGasLimit);
    }

    function setMinTimeDelayPublic(
        uint256 _minTimeDelayPublic
    ) external onlyOwner {
        require(
            _minTimeDelayPublic <= MAX_MIN_TIME_DELAY_PUBLIC,
            "BasePositionManager: minTimeDelayPublic is too high"
        );
        minTimeDelayPublic = _minTimeDelayPublic;
        emit SetMinTimeDelayPublic(_minTimeDelayPublic);
    }

    function setDepositFee(uint256 _depositFee) external onlyOwner {
        require(
            _depositFee <= MAX_DEPOSIT_FEE,
            "BasePositionManager: depositFee is too high"
        );
        depositFee = _depositFee;
        emit SetDepositFee(_depositFee);
    }

    function setIncreasePositionBufferBps(
        uint256 _increasePositionBufferBps
    ) external onlyOwner {
        require(
            _increasePositionBufferBps <= MAX_INCREASE_POSITION_BUFFER_BPS,
            "BasePositionManager: increasePositionBufferBps is too high"
        );
        increasePositionBufferBps = _increasePositionBufferBps;
        emit SetIncreasePositionBufferBps(_increasePositionBufferBps);
    }

    function setMaxGlobalSizes(
        address[] memory _tokens,
        uint256[] memory _longSizes,
        uint256[] memory _shortSizes
    ) external onlyOwner {
        for (uint256 i = 0; i < _tokens.length; i++) {
            address token = _tokens[i];
            maxGlobalLongSizes[token] = _longSizes[i];
            maxGlobalShortSizes[token] = _shortSizes[i];
        }

        emit SetMaxGlobalSizes(_tokens, _longSizes, _shortSizes);
    }

    function withdrawFees(address _token, address _receiver) external override {
        require(
            msg.sender == addressesProvider.getPhlpManager(),
            "BasePositionManager: Only PhlpManager can withdraw fee"
        );

        uint256 amount = feeReserves[_token];
        if (amount == 0) {
            return;
        }

        feeReserves[_token] = 0;
        IERC20(_token).safeTransfer(_receiver, amount);

        emit WithdrawFees(_token, _receiver, amount);
    }

    function _increasePosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        uint256 _sizeDelta,
        bool _isLong,
        uint256 _price
    ) internal {
        IVault vault = IVault(addressesProvider.getVault());

        uint256 markPrice = IPhamePriceOracle(
            addressesProvider.getPriceOracle()
        ).getPrice(_indexToken, _isLong);
        if (_isLong) {
            require(
                markPrice <= _price,
                "BasePositionManager: mark price higher than limit"
            );
        } else {
            require(
                markPrice >= _price,
                "BasePositionManager: mark price lower than limit"
            );
        }

        if (_isLong) {
            uint256 maxGlobalLongSize = maxGlobalLongSizes[_indexToken];
            if (
                maxGlobalLongSize > 0 &&
                vault.guaranteedUsd(_indexToken).add(_sizeDelta) >
                maxGlobalLongSize
            ) {
                revert("BasePositionManager: max global longs exceeded");
            }
        } else {
            uint256 maxGlobalShortSize = maxGlobalShortSizes[_indexToken];
            if (
                maxGlobalShortSize > 0 &&
                vault.globalShortSizes(_indexToken).add(_sizeDelta) >
                maxGlobalShortSize
            ) {
                revert("BasePositionManager: max global shorts exceeded");
            }
        }

        IShortsTracker(addressesProvider.getShortsTracker())
            .updateGlobalShortData(
                _account,
                _collateralToken,
                _indexToken,
                _isLong,
                _sizeDelta,
                markPrice,
                true
            );
        IRouter(addressesProvider.getRouter()).pluginIncreasePosition(
            _account,
            _collateralToken,
            _indexToken,
            _sizeDelta,
            _isLong
        );
    }

    function _decreasePosition(
        address _account,
        address _collateralToken,
        address _indexToken,
        uint256 _collateralDelta,
        uint256 _sizeDelta,
        bool _isLong,
        address _receiver,
        uint256 _price
    ) internal returns (uint256) {
        uint256 markPrice = IPhamePriceOracle(
            addressesProvider.getPriceOracle()
        ).getPrice(_indexToken, !_isLong);
        if (_isLong) {
            require(
                markPrice >= _price,
                "BasePositionManager: mark price lower than limit"
            );
        } else {
            require(
                markPrice <= _price,
                "BasePositionManager: mark price higher than limit"
            );
        }

        IShortsTracker(addressesProvider.getShortsTracker())
            .updateGlobalShortData(
                _account,
                _collateralToken,
                _indexToken,
                _isLong,
                _sizeDelta,
                markPrice,
                false
            );
        uint256 amountOut = IRouter(addressesProvider.getRouter())
            .pluginDecreasePosition(
                _account,
                _collateralToken,
                _indexToken,
                _collateralDelta,
                _sizeDelta,
                _isLong,
                _receiver
            );

        return amountOut;
    }

    function _swap(
        address[] memory _path,
        uint256 _minOut,
        address _receiver
    ) internal returns (uint256) {
        if (_path.length == 2) {
            return _vaultSwap(_path[0], _path[1], _minOut, _receiver);
        }
        revert("BasePositionManager: invalid _path.length");
    }

    function _vaultSwap(
        address _tokenIn,
        address _tokenOut,
        uint256 _minOut,
        address _receiver
    ) internal returns (uint256) {
        uint256 amountOut = IVault(addressesProvider.getVault()).swap(
            _tokenIn,
            _tokenOut,
            _receiver
        );
        require(
            amountOut >= _minOut,
            "BasePositionManager: insufficient amountOut"
        );
        return amountOut;
    }

    function _transferInETH() internal {
        if (msg.value != 0) {
            IWETH(weth).deposit{value: msg.value}();
        }
    }

    function _transferOutETHWithGasLimitFallbackToWeth(
        uint256 _amountOut,
        address payable _receiver
    ) internal {
        IWETH _weth = IWETH(weth);
        _weth.withdraw(_amountOut);

        (bool success /* bytes memory data */, ) = _receiver.call{
            value: _amountOut,
            gas: ethTransferGasLimit
        }("");

        if (success) {
            return;
        }

        // if the transfer failed, re-wrap the token and send it to the receiver
        _weth.deposit{value: _amountOut}();
        _weth.transfer(address(_receiver), _amountOut);
    }

    function _collectFees(
        address _account,
        address[] memory _path,
        uint256 _amountIn,
        address _indexToken,
        bool _isLong,
        uint256 _sizeDelta
    ) internal returns (uint256) {
        bool shouldDeductFee = _shouldDeductFee(
            _account,
            _path,
            _amountIn,
            _indexToken,
            _isLong,
            _sizeDelta
        );

        if (shouldDeductFee) {
            uint256 afterFeeAmount = _amountIn
                .mul(BASIS_POINTS_DIVISOR.sub(depositFee))
                .div(BASIS_POINTS_DIVISOR);
            uint256 feeAmount = _amountIn.sub(afterFeeAmount);
            address feeToken = _path[_path.length - 1];
            feeReserves[feeToken] = feeReserves[feeToken].add(feeAmount);
            return afterFeeAmount;
        }

        return _amountIn;
    }

    function _shouldDeductFee(
        address _account,
        address[] memory _path,
        uint256 _amountIn,
        address _indexToken,
        bool _isLong,
        uint256 _sizeDelta
    ) internal view returns (bool) {
        // if the position is a short, do not charge a fee
        if (!_isLong) {
            return false;
        }

        // if the position size is not increasing, this is a collateral deposit
        if (_sizeDelta == 0) {
            return true;
        }

        address collateralToken = _path[_path.length - 1];

        IVault vault = IVault(addressesProvider.getVault());
        (uint256 size, uint256 collateral, , , , , , ) = vault.getPosition(
            _account,
            collateralToken,
            _indexToken,
            _isLong
        );

        // if there is no existing position, do not charge a fee
        if (size == 0) {
            return false;
        }

        uint256 nextSize = size.add(_sizeDelta);
        uint256 collateralDelta = vault.tokenToUsdMin(
            collateralToken,
            _amountIn
        );
        uint256 nextCollateral = collateral.add(collateralDelta);

        uint256 prevLeverage = size.mul(BASIS_POINTS_DIVISOR).div(collateral);
        // allow for a maximum of a increasePositionBufferBps decrease since there might be some swap fees taken from the collateral
        uint256 nextLeverage = nextSize
            .mul(BASIS_POINTS_DIVISOR + increasePositionBufferBps)
            .div(nextCollateral);

        // deduct a fee if the leverage is decreased
        return nextLeverage < prevLeverage;
    }
}
          

contracts/protocol/libraries/types/DataTypes.sol

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;

library DataTypes {
    struct VaultConfig {
        bool isSwapEnabled;
        bool isLeverageEnabled;
        uint256 maxLeverage;
        // fees
        uint256 taxBps;
        uint256 stableTaxBps;
        uint256 mintBurnFeeBps;
        uint256 swapFeeBps;
        uint256 stableSwapFeeBps;
        uint256 marginFeeBps;
        uint256 liquidationFeeUsd;
        uint256 minProfitTime;
        bool hasDynamicFees;
        // staking
        uint256 stakingBps;
        // funding rate
        uint256 fundingInterval;
        uint256 fundingRateFactor;
        uint256 stableFundingRateFactor;
    }

    struct TokenConfig {
        // should always be true if token exists
        bool isWhitelisted;
        // basic parameters
        uint256 decimals;
        uint256 weight; // customisation of index composition
        uint256 minProfitBps;
        uint256 maxUsdphAmount; // a max amount of USDPH debt for a token
        bool isStable;
        bool isShortable;
        // risk parameters
        // bufferAmount allows specification of an amount to exclude from swaps
        // this can be used to ensure a certain amount of liquidity is available for leverage positions
        uint256 bufferAmount;
        uint256 maxGlobalShortSize;
    }

    struct TokenConfigs {
        uint256 totalTokenWeights;
        address[] allWhitelistedTokens;
        mapping(address => TokenConfig) tokenConfigs;
    }
}
          

Compiler Settings

{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"istanbul"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"addressesProvider_","internalType":"contract IAddressesProvider"},{"type":"address","name":"_weth","internalType":"address"},{"type":"uint256","name":"_depositFee","internalType":"uint256"},{"type":"uint256","name":"_minExecutionFee","internalType":"uint256"}]},{"type":"event","name":"CancelDecreasePosition","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address[]","name":"path","internalType":"address[]","indexed":false},{"type":"address","name":"indexToken","internalType":"address","indexed":false},{"type":"uint256","name":"collateralDelta","internalType":"uint256","indexed":false},{"type":"uint256","name":"sizeDelta","internalType":"uint256","indexed":false},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"address","name":"receiver","internalType":"address","indexed":false},{"type":"uint256","name":"acceptablePrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"minOut","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockGap","internalType":"uint256","indexed":false},{"type":"uint256","name":"timeGap","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CancelIncreasePosition","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address[]","name":"path","internalType":"address[]","indexed":false},{"type":"address","name":"indexToken","internalType":"address","indexed":false},{"type":"uint256","name":"amountIn","internalType":"uint256","indexed":false},{"type":"uint256","name":"minOut","internalType":"uint256","indexed":false},{"type":"uint256","name":"sizeDelta","internalType":"uint256","indexed":false},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"uint256","name":"acceptablePrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockGap","internalType":"uint256","indexed":false},{"type":"uint256","name":"timeGap","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CreateDecreasePosition","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address[]","name":"path","internalType":"address[]","indexed":false},{"type":"address","name":"indexToken","internalType":"address","indexed":false},{"type":"uint256","name":"collateralDelta","internalType":"uint256","indexed":false},{"type":"uint256","name":"sizeDelta","internalType":"uint256","indexed":false},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"address","name":"receiver","internalType":"address","indexed":false},{"type":"uint256","name":"acceptablePrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"minOut","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"index","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockTime","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CreateIncreasePosition","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address[]","name":"path","internalType":"address[]","indexed":false},{"type":"address","name":"indexToken","internalType":"address","indexed":false},{"type":"uint256","name":"amountIn","internalType":"uint256","indexed":false},{"type":"uint256","name":"minOut","internalType":"uint256","indexed":false},{"type":"uint256","name":"sizeDelta","internalType":"uint256","indexed":false},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"uint256","name":"acceptablePrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"index","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockTime","internalType":"uint256","indexed":false},{"type":"uint256","name":"gasPrice","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExecuteDecreasePosition","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address[]","name":"path","internalType":"address[]","indexed":false},{"type":"address","name":"indexToken","internalType":"address","indexed":false},{"type":"uint256","name":"collateralDelta","internalType":"uint256","indexed":false},{"type":"uint256","name":"sizeDelta","internalType":"uint256","indexed":false},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"address","name":"receiver","internalType":"address","indexed":false},{"type":"uint256","name":"acceptablePrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"minOut","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockGap","internalType":"uint256","indexed":false},{"type":"uint256","name":"timeGap","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExecuteIncreasePosition","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address[]","name":"path","internalType":"address[]","indexed":false},{"type":"address","name":"indexToken","internalType":"address","indexed":false},{"type":"uint256","name":"amountIn","internalType":"uint256","indexed":false},{"type":"uint256","name":"minOut","internalType":"uint256","indexed":false},{"type":"uint256","name":"sizeDelta","internalType":"uint256","indexed":false},{"type":"bool","name":"isLong","internalType":"bool","indexed":false},{"type":"uint256","name":"acceptablePrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockGap","internalType":"uint256","indexed":false},{"type":"uint256","name":"timeGap","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SetDelayValues","inputs":[{"type":"uint256","name":"minBlockDelayKeeper","internalType":"uint256","indexed":false},{"type":"uint256","name":"maxTimeDelay","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetDepositFee","inputs":[{"type":"uint256","name":"depositFee","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetEthTransferGasLimit","inputs":[{"type":"uint256","name":"ethTransferGasLimit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetIncreasePositionBufferBps","inputs":[{"type":"uint256","name":"increasePositionBufferBps","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetIsLeverageEnabled","inputs":[{"type":"bool","name":"isLeverageEnabled","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"SetMaxGlobalSizes","inputs":[{"type":"address[]","name":"tokens","internalType":"address[]","indexed":false},{"type":"uint256[]","name":"longSizes","internalType":"uint256[]","indexed":false},{"type":"uint256[]","name":"shortSizes","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"SetMinExecutionFee","inputs":[{"type":"uint256","name":"minExecutionFee","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetMinTimeDelayPublic","inputs":[{"type":"uint256","name":"minTimeDelayPublic","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetPositionKeeper","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isActive","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"SetRequestKeysStartValues","inputs":[{"type":"uint256","name":"increasePositionRequestKeysStart","internalType":"uint256","indexed":false},{"type":"uint256","name":"decreasePositionRequestKeysStart","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"WithdrawFees","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"address","name":"receiver","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"BASIS_POINTS_DIVISOR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_DEPOSIT_FEE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_INCREASE_POSITION_BUFFER_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_MAX_TIME_DELAY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_MIN_BLOCK_DELAY_KEEPER","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_MIN_EXECUTION_FEE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_MIN_TIME_DELAY_PUBLIC","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IAddressesProvider"}],"name":"addressesProvider","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"cancelDecreasePosition","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"},{"type":"address","name":"_executionFeeReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"cancelIncreasePosition","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"},{"type":"address","name":"_executionFeeReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"createDecreasePosition","inputs":[{"type":"address[]","name":"_path","internalType":"address[]"},{"type":"address","name":"_indexToken","internalType":"address"},{"type":"uint256","name":"_collateralDelta","internalType":"uint256"},{"type":"uint256","name":"_sizeDelta","internalType":"uint256"},{"type":"bool","name":"_isLong","internalType":"bool"},{"type":"address","name":"_receiver","internalType":"address"},{"type":"uint256","name":"_acceptablePrice","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"},{"type":"uint256","name":"_executionFee","internalType":"uint256"},{"type":"bool","name":"_withdrawETH","internalType":"bool"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"createIncreasePosition","inputs":[{"type":"address[]","name":"_path","internalType":"address[]"},{"type":"address","name":"_indexToken","internalType":"address"},{"type":"uint256","name":"_amountIn","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"},{"type":"uint256","name":"_sizeDelta","internalType":"uint256"},{"type":"bool","name":"_isLong","internalType":"bool"},{"type":"uint256","name":"_acceptablePrice","internalType":"uint256"},{"type":"uint256","name":"_executionFee","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"createIncreasePositionETH","inputs":[{"type":"address[]","name":"_path","internalType":"address[]"},{"type":"address","name":"_indexToken","internalType":"address"},{"type":"uint256","name":"_minOut","internalType":"uint256"},{"type":"uint256","name":"_sizeDelta","internalType":"uint256"},{"type":"bool","name":"_isLong","internalType":"bool"},{"type":"uint256","name":"_acceptablePrice","internalType":"uint256"},{"type":"uint256","name":"_executionFee","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"decreasePositionRequestKeys","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"decreasePositionRequestKeysStart","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"account","internalType":"address"},{"type":"address","name":"indexToken","internalType":"address"},{"type":"uint256","name":"collateralDelta","internalType":"uint256"},{"type":"uint256","name":"sizeDelta","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"address","name":"receiver","internalType":"address"},{"type":"uint256","name":"acceptablePrice","internalType":"uint256"},{"type":"uint256","name":"minOut","internalType":"uint256"},{"type":"uint256","name":"executionFee","internalType":"uint256"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"uint256","name":"blockTime","internalType":"uint256"},{"type":"bool","name":"withdrawETH","internalType":"bool"}],"name":"decreasePositionRequests","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"decreasePositionsIndex","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"depositFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"ethTransferGasLimit","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"executeDecreasePosition","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"},{"type":"address","name":"_executionFeeReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeDecreasePositions","inputs":[{"type":"uint256","name":"_endIndex","internalType":"uint256"},{"type":"address","name":"_executionFeeReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"executeIncreasePosition","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"},{"type":"address","name":"_executionFeeReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeIncreasePositions","inputs":[{"type":"uint256","name":"_endIndex","internalType":"uint256"},{"type":"address","name":"_executionFeeReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"feeReserves","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getDecreasePositionRequestPath","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getIncreasePositionRequestPath","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRequestKey","inputs":[{"type":"address","name":"_account","internalType":"address"},{"type":"uint256","name":"_index","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"}],"name":"getRequestQueueLengths","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"increasePositionBufferBps","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"increasePositionRequestKeys","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"increasePositionRequestKeysStart","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"account","internalType":"address"},{"type":"address","name":"indexToken","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"minOut","internalType":"uint256"},{"type":"uint256","name":"sizeDelta","internalType":"uint256"},{"type":"bool","name":"isLong","internalType":"bool"},{"type":"uint256","name":"acceptablePrice","internalType":"uint256"},{"type":"uint256","name":"executionFee","internalType":"uint256"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"uint256","name":"blockTime","internalType":"uint256"},{"type":"bool","name":"hasCollateralInETH","internalType":"bool"}],"name":"increasePositionRequests","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"increasePositionsIndex","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isPositionKeeper","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxGlobalLongSizes","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxGlobalShortSizes","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxTimeDelay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minBlockDelayKeeper","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minExecutionFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minTimeDelayPublic","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDelayValues","inputs":[{"type":"uint256","name":"_minBlockDelayKeeper","internalType":"uint256"},{"type":"uint256","name":"_maxTimeDelay","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDepositFee","inputs":[{"type":"uint256","name":"_depositFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setEthTransferGasLimit","inputs":[{"type":"uint256","name":"_ethTransferGasLimit","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setIncreasePositionBufferBps","inputs":[{"type":"uint256","name":"_increasePositionBufferBps","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxGlobalSizes","inputs":[{"type":"address[]","name":"_tokens","internalType":"address[]"},{"type":"uint256[]","name":"_longSizes","internalType":"uint256[]"},{"type":"uint256[]","name":"_shortSizes","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinExecutionFee","inputs":[{"type":"uint256","name":"_minExecutionFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinTimeDelayPublic","inputs":[{"type":"uint256","name":"_minTimeDelayPublic","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPositionKeeper","inputs":[{"type":"address","name":"_account","internalType":"address"},{"type":"bool","name":"_isActive","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRequestKeysStartValues","inputs":[{"type":"uint256","name":"_increasePositionRequestKeysStart","internalType":"uint256"},{"type":"uint256","name":"_decreasePositionRequestKeysStart","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"weth","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFees","inputs":[{"type":"address","name":"_token","internalType":"address"},{"type":"address","name":"_receiver","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

0x60c06040526207a12060025560646005553480156200001d57600080fd5b50604051620060f5380380620060f5833981810160405260808110156200004357600080fd5b508051602082015160408301516060909301516001600090815592939192849084908490620000716200021e565b600180546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038316620001065760405162461bcd60e51b8152600401808060200182810382526036815260200180620060696036913960400191505060405180910390fd5b6001600160a01b0382166200014d5760405162461bcd60e51b8152600401808060200182810382526029815260200180620060406029913960400191505060405180910390fd5b60648111156200018f5760405162461bcd60e51b815260040180806020018281038252602b8152602001806200609f602b913960400191505060405180910390fd5b6001600160601b0319606093841b81166080529190921b1660a05260045569d3c21bcecceda1000000811115620001f85760405162461bcd60e51b815260040180806020018281038252602b815260200180620060ca602b913960400191505060405180910390fd5b6009555050306000908152601060205260409020805460ff191660011790555062000222565b3390565b60805160601c60a05160601c615d9a620002a66000398061034952806116f55280612455528061333552806140e252806143085250806113625280611f005280612f8552806130d3528061360e5280613c2f5280613dbc5280613ed152806147f252806148955280614bb85280614ccd528061521c52806153ad5250615d9a6000f3fe6080604052600436106103395760003560e01c806363ae2103116101ab578063cb0269c9116100f7578063f255527811610095578063f3883d8b1161006f578063f3883d8b14610f8f578063fa44457714610fc8578063faf990f314610ffb578063fc2cee6214611089576103a7565b8063f255527814610ee6578063f2cea6a514610f21578063f2fde38b14610f5c576103a7565b8063e70dd2fc116100d1578063e70dd2fc14610c28578063e8caee1c14610d0a578063ec2a1bf214610d1f578063ef12c67e14610d34576103a7565b8063cb0269c914610b2e578063ceed2cc114610b43578063d467a4ae14610c13576103a7565b80639698d25a116101645780639b5786201161013e5780639b57862014610abf578063a4e7684f14610ad4578063c6d87dd514610b04578063c72c4d1014610b19576103a7565b80639698d25a14610a3e57806398d1e03a14610a715780639a20810014610a86576103a7565b806363ae2103146109ab57806367a52793146109c0578063715018a6146109d55780638da5cb5b146109ea5780638f649494146109ff57806395e9bbd714610a14576103a7565b80632d79cf42116102855780634278555f116102235780635d5c22e8116101fd5780635d5c22e81461088c57806360a362e21461090657806362f8a3fe1461093f578063633451de14610978576103a7565b80634278555f14610823578063490ae2101461084d5780635841fcaa14610877576103a7565b806336eba48a1161025f57806336eba48a146107805780633a2a80c7146107b35780633a9b52ad146107c85780633fc8cef3146107f2576103a7565b80632d79cf4214610700578063308aa81f146107155780633422ead114610745576103a7565b80631bca8cf0116102f2578063225fc9fd116102cc578063225fc9fd1461063a578063233bfe3b1461067357806327b42c0f1461069d5780632b73fb18146106d6576103a7565b80631bca8cf0146105465780631ce9cb8f1461055b5780631f2851061461058e576103a7565b806304225954146103ac5780630d4d003d146103e85780631045c74e14610435578063126082cf14610468578063133e5b171461047d57806315de638614610468576103a7565b366103a757336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103a55760405162461bcd60e51b8152600401808060200182810382526023815260200180615c8e6023913960400191505060405180910390fd5b005b600080fd5b3480156103b857600080fd5b506103d6600480360360208110156103cf57600080fd5b50356110b3565b60408051918252519081900360200190f35b3480156103f457600080fd5b506104216004803603604081101561040b57600080fd5b50803590602001356001600160a01b03166110d4565b604080519115158252519081900360200190f35b34801561044157600080fd5b506103d66004803603602081101561045857600080fd5b50356001600160a01b03166115c4565b34801561047457600080fd5b506103d66115d6565b6103a5600480360360e081101561049357600080fd5b810190602081018135600160201b8111156104ad57600080fd5b8201836020820111156104bf57600080fd5b803590602001918460208302840111600160201b831117156104e057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b0383351693505050602081013590604081013590606081013515159060808101359060a001356115dc565b34801561055257600080fd5b506103d66117c5565b34801561056757600080fd5b506103d66004803603602081101561057e57600080fd5b50356001600160a01b03166117cb565b34801561059a57600080fd5b506105b8600480360360208110156105b157600080fd5b50356117dd565b604051808d6001600160a01b031681526020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200184815260200183815260200182151581526020019c5050505050505050505050505060405180910390f35b34801561064657600080fd5b506104216004803603604081101561065d57600080fd5b50803590602001356001600160a01b0316611849565b34801561067f57600080fd5b506103a56004803603602081101561069657600080fd5b5035611be9565b3480156106a957600080fd5b50610421600480360360408110156106c057600080fd5b50803590602001356001600160a01b0316611cc7565b3480156106e257600080fd5b506103a5600480360360208110156106f957600080fd5b50356120c8565b34801561070c57600080fd5b506103d66121a6565b34801561072157600080fd5b506103a56004803603604081101561073857600080fd5b50803590602001356121ac565b34801561075157600080fd5b506103a56004803603604081101561076857600080fd5b506001600160a01b03813516906020013515156122d9565b34801561078c57600080fd5b50610421600480360360208110156107a357600080fd5b50356001600160a01b031661239b565b3480156107bf57600080fd5b506103d66123b0565b3480156107d457600080fd5b506103a5600480360360208110156107eb57600080fd5b50356123b6565b3480156107fe57600080fd5b50610807612453565b604080516001600160a01b039092168252519081900360200190f35b34801561082f57600080fd5b506103d66004803603602081101561084657600080fd5b5035612477565b34801561085957600080fd5b506103a56004803603602081101561087057600080fd5b5035612487565b34801561088357600080fd5b506103d6612564565b34801561089857600080fd5b506108b6600480360360208110156108af57600080fd5b503561256a565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108f25781810151838201526020016108da565b505050509050019250505060405180910390f35b34801561091257600080fd5b506104216004803603604081101561092957600080fd5b50803590602001356001600160a01b031661268e565b34801561094b57600080fd5b506103d66004803603604081101561096257600080fd5b506001600160a01b038135169060200135612a14565b34801561098457600080fd5b506103d66004803603602081101561099b57600080fd5b50356001600160a01b0316612a5a565b3480156109b757600080fd5b506103d6612a6c565b3480156109cc57600080fd5b506103d6612a72565b3480156109e157600080fd5b506103a5612a78565b3480156109f657600080fd5b50610807612b24565b348015610a0b57600080fd5b506103d6612b33565b348015610a2057600080fd5b506108b660048036036020811015610a3757600080fd5b5035612b41565b348015610a4a57600080fd5b506103d660048036036020811015610a6157600080fd5b50356001600160a01b0316612c57565b348015610a7d57600080fd5b506103d6612c69565b348015610a9257600080fd5b506103a560048036036040811015610aa957600080fd5b50803590602001356001600160a01b0316612c6f565b348015610acb57600080fd5b506103d6612e4c565b348015610ae057600080fd5b506103a560048036036040811015610af757600080fd5b5080359060200135612e52565b348015610b1057600080fd5b506103d6612f7e565b348015610b2557600080fd5b50610807612f83565b348015610b3a57600080fd5b506103d6612fa7565b6103a56004803603610100811015610b5a57600080fd5b810190602081018135600160201b811115610b7457600080fd5b820183602082011115610b8657600080fd5b803590602001918460208302840111600160201b83111715610ba757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b0383351693505050602081013590604081013590606081013590608081013515159060a08101359060c00135612fad565b348015610c1f57600080fd5b506103d6613212565b6103a56004803603610140811015610c3f57600080fd5b810190602081018135600160201b811115610c5957600080fd5b820183602082011115610c6b57600080fd5b803590602001918460208302840111600160201b83111715610c8c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505081356001600160a01b0390811693506020830135926040810135925060608101351515916080820135169060a08101359060c08101359060e08101359061010001351515613217565b348015610d1657600080fd5b506103d66133fc565b348015610d2b57600080fd5b506103d6613402565b348015610d4057600080fd5b506103a560048036036060811015610d5757600080fd5b810190602081018135600160201b811115610d7157600080fd5b820183602082011115610d8357600080fd5b803590602001918460208302840111600160201b83111715610da457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610df357600080fd5b820183602082011115610e0557600080fd5b803590602001918460208302840111600160201b83111715610e2657600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610e7557600080fd5b820183602082011115610e8757600080fd5b803590602001918460208302840111600160201b83111715610ea857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613408945050505050565b348015610ef257600080fd5b506103a560048036036040811015610f0957600080fd5b506001600160a01b038135811691602001351661360c565b348015610f2d57600080fd5b50610f3661376e565b604080519485526020850193909352838301919091526060830152519081900360800190f35b348015610f6857600080fd5b506103a560048036036020811015610f7f57600080fd5b50356001600160a01b0316613780565b348015610f9b57600080fd5b506103a560048036036040811015610fb257600080fd5b50803590602001356001600160a01b0316613883565b348015610fd457600080fd5b506103d660048036036020811015610feb57600080fd5b50356001600160a01b0316613a5f565b34801561100757600080fd5b506110256004803603602081101561101e57600080fd5b5035613a71565b604080516001600160a01b039c8d1681529a909b1660208b0152898b01989098526060890196909652608088019490945291151560a087015260c086015260e085015261010084015261012083015215156101408201529051908190036101600190f35b34801561109557600080fd5b506103a5600480360360208110156110ac57600080fd5b5035613adb565b600c81815481106110c357600080fd5b600091825260209091200154905081565b60006002600054141561111c576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260146020908152604080832081516101a08101835281546001600160a01b0316815260018201805484518187028101870190955280855291949293858401939092908301828280156111a157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611183575b505050918352505060028201546001600160a01b0390811660208301526003830154604083015260048301546060830152600583015460ff8082161515608085015261010091829004831660a0850152600685015460c0850152600785015460e08501526008850154918401919091526009840154610120840152600a840154610140840152600b9093015490921615156101609091015281519192501661124d5760019150506115b9565b60006112688261014001518361016001518460000151613bc1565b90508061127a576000925050506115b9565b600085815260146020526040812080546001600160a01b0319168155906112a4600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820180546001600160a81b031916905560068201819055600782018190556008820181905560098201819055600a8201819055600b909101805460ff19169055825160208401518051611347929190849061132057fe5b60200260200101518560400151866060015187608001518860a00151308a60e00151613c2a565b9050801561146e576001836020015151111561142f576114187f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b1580156113b957600080fd5b505afa1580156113cd573d6000803e3d6000fd5b505050506040513d60208110156113e357600080fd5b5051602085015180518491906000906113f857fe5b60200260200101516001600160a01b03166140099092919063ffffffff16565b61142c836020015184610100015130614060565b90505b8261018001511561144d57611448818460c001516140de565b61146e565b61146e8360c00151828560200151600187602001515103815181106113f857fe5b61147d836101200151866140de565b82600001516001600160a01b03167f21435c5b618d77ff3657140cd3318e2cffaebc5e0e1b7318f56a9ba4044c3ed284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001518c61012001516114f38e6101400151436142a390919063ffffffff16565b6101608f01516115049042906142a3565b60405180806020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200184815260200183815260200182810382528d818151815260200191508051906020019060200280838360005b8381101561159457818101518382015260200161157c565b505050509050019c5050505050505050505050505060405180910390a2600193505050505b600160005592915050565b60076020526000908152604090205481565b61271081565b60026000541415611622576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b60026000556009548110156116685760405162461bcd60e51b81526004018080602001828103825260248152602001806159286024913960400191505060405180910390fd5b803410156116a75760405162461bcd60e51b815260040180806020018281038252602181526020018061596c6021913960400191505060405180910390fd5b8651600114806116b8575086516002145b6116f35760405162461bcd60e51b8152600401808060200182810382526024815260200180615a716024913960400191505060405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168760008151811061172a57fe5b60200260200101516001600160a01b03161461178d576040805162461bcd60e51b815260206004820152601d60248201527f506f736974696f6e526f757465723a20696e76616c6964205f70617468000000604482015290519081900360640190fd5b611795614300565b60006117a134836142a3565b90506117b6338989848a8a8a8a8a600161437d565b50506001600055505050505050565b600f5481565b60066020526000908152604090205481565b6014602052600090815260409020805460028201546003830154600484015460058501546006860154600787015460088801546009890154600a8a0154600b909a01546001600160a01b03998a169a988a16999798969760ff808816986101009098049091169691168c565b600060026000541415611891576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260126020908152604080832081516101808101835281546001600160a01b03168152600182018054845181870281018701909552808552919492938584019390929083018282801561191657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116118f8575b505050918352505060028201546001600160a01b039081166020830152600383015460408301526004830154606083015260058301546080830152600683015460ff908116151560a0840152600784015460c0840152600884015460e08401526009840154610100840152600a840154610120840152600b909301549092161515610140909101528151919250166119b25760019150506115b9565b60006119cd826101200151836101400151846000015161464d565b9050806119df576000925050506115b9565b600085815260126020526040812080546001600160a01b031916815590611a09600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820181905560068201805460ff19908116909155600783018290556008830182905560098301829055600a830191909155600b9091018054909116905561016082015115611a8d57611a88826060015183600001516140de565b611aab565b611aab8260000151836060015184602001516000815181106113f857fe5b611aba826101000151856140de565b81600001516001600160a01b03167f35b638e650e2328786fb405bd69d2083dbedc018d086662e74b775b4f1dae4bf83602001518460400151856060015186608001518760a001518860c001518960e001518a6101000151611b2a8c6101200151436142a390919063ffffffff16565b6101408d0151611b3b9042906142a3565b60405180806020018b6001600160a01b031681526020018a8152602001898152602001888152602001871515815260200186815260200185815260200184815260200183815260200182810382528c818151815260200191508051906020019060200280838360005b83811015611bbc578181015183820152602001611ba4565b505050509050019b50505050505050505050505060405180910390a2600192505050600160005592915050565b611bf161470b565b6001600160a01b0316611c02612b24565b6001600160a01b031614611c4b576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b612710811115611c8c5760405162461bcd60e51b815260040180806020018281038252603a815260200180615bef603a913960400191505060405180910390fd5b60058190556040805182815290517f21167d0d4661af93817ebce920f18986eed3d75d5e1c03f2aed05efcbafbc4529181900360200190a150565b600060026000541415611d0f576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260126020908152604080832081516101808101835281546001600160a01b031681526001820180548451818702810187019095528085529194929385840193909290830182828015611d9457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d76575b505050918352505060028201546001600160a01b039081166020830152600383015460408301526004830154606083015260058301546080830152600683015460ff908116151560a0840152600784015460c0840152600884015460e08401526009840154610100840152600a840154610120840152600b90930154909216151561014090910152815191925016611e305760019150506115b9565b6000611e4b8261012001518361014001518460000151613bc1565b905080611e5d576000925050506115b9565b600085815260126020526040812080546001600160a01b031916815590611e87600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820181905560068201805460ff19908116909155600783018290556008830182905560098301829055600a830191909155600b9091018054909116905560608201511561200b5760008260600151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5757600080fd5b505afa158015611f6b573d6000803e3d6000fd5b505050506040513d6020811015611f8157600080fd5b505160208501515190915060011015611fc457611fae81856060015186602001516000815181106113f857fe5b611fc18460200151856080015130614060565b91505b6000611fe8856000015186602001518588604001518960c001518a60a0015161470f565b905061200782828760200151600189602001515103815181106113f857fe5b5050505b815160208301518051612049929190600019810190811061202857fe5b602002602001015184604001518560a001518660c001518760e001516147ee565b612058826101000151856140de565b81600001516001600160a01b03167f1be316b94d38c07bd41cdb4913772d0a0a82802786a2f8b657b6e85dbcdfc64183602001518460400151856060015186608001518760a001518860c001518960e001518a6101000151611b2a8c6101200151436142a390919063ffffffff16565b6120d061470b565b6001600160a01b03166120e1612b24565b6001600160a01b03161461212a576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b61025881111561216b5760405162461bcd60e51b8152600401808060200182810382526033815260200180615b1f6033913960400191505060405180910390fd5b60038190556040805182815290517fbd7411e312e9c7c95b6798503250129c3b613975a11dc36e76f469c5b8e8bcd59181900360200190a150565b60025481565b6121b461470b565b6001600160a01b03166121c5612b24565b6001600160a01b03161461220e576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b600c5482111561224f5760405162461bcd60e51b815260040180806020018281038252603c815260200180615a06603c913960400191505060405180910390fd5b600d548111156122905760405162461bcd60e51b815260040180806020018281038252603c815260200180615c52603c913960400191505060405180910390fd5b600e829055600f819055604080518381526020810183905281517febb0f666150f4be5b60c45df8f3e49992510b0128027fe58eea6110f296493bc929181900390910190a15050565b6122e161470b565b6001600160a01b03166122f2612b24565b6001600160a01b03161461233b576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b6001600160a01b038216600081815260106020908152604091829020805460ff1916851515908117909155825190815291517ffbabc02389290a451c6e600d05bf9887b99bfad39d8e1237e4e3df042e4941fe9281900390910190a25050565b60106020526000908152604090205460ff1681565b60035481565b6123be61470b565b6001600160a01b03166123cf612b24565b6001600160a01b031614612418576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b60028190556040805182815290517f4d371d598d3a13f99ce992a17975bbaf1e1c256e072ec7d2f93ce88e40d9ba1c9181900360200190a150565b7f000000000000000000000000000000000000000000000000000000000000000081565b600d81815481106110c357600080fd5b61248f61470b565b6001600160a01b03166124a0612b24565b6001600160a01b0316146124e9576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b60648111156125295760405162461bcd60e51b815260040180806020018281038252602b815260200180615ac5602b913960400191505060405180910390fd5b60048190556040805182815290517f974fd3c1fcb4653dfc4fb740c4c692cd212d55c28f163f310128cb64d83006759181900360200190a150565b600a5481565b600081815260146020908152604080832081516101a08101835281546001600160a01b0316815260018201805484518187028101870190955280855260609695929485840193909291908301828280156125ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116125cf575b505050918352505060028201546001600160a01b039081166020808401919091526003840154604084015260048401546060840152600584015460ff808216151560808601526101009182900490931660a0850152600685015460c0850152600785015460e08501526008850154908401526009840154610120840152600a840154610140840152600b909301541615156101609091015201519392505050565b6000600260005414156126d6576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260146020908152604080832081516101a08101835281546001600160a01b03168152600182018054845181870281018701909552808552919492938584019390929083018282801561275b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161273d575b505050918352505060028201546001600160a01b0390811660208301526003830154604083015260048301546060830152600583015460ff8082161515608085015261010091829004831660a0850152600685015460c0850152600785015460e08501526008850154918401919091526009840154610120840152600a840154610140840152600b909301549092161515610160909101528151919250166128075760019150506115b9565b6000612822826101400151836101600151846000015161464d565b905080612834576000925050506115b9565b600085815260146020526040812080546001600160a01b03191681559061285e600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820180546001600160a81b031916905560068201819055600782018190556008820181905560098201819055600a820155600b01805460ff191690556101208201516128cf90856140de565b81600001516001600160a01b03167f87abfd78e844f28318363bdf3da99eab2f4a2da9ff7ae365484507f7b6c3f80583602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001516129458d6101400151436142a390919063ffffffff16565b6101608e01516129569042906142a3565b60405180806020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200184815260200183815260200182810382528d818151815260200191508051906020019060200280838360005b838110156129e65781810151838201526020016129ce565b505050509050019c5050505050505050505050505060405180910390a2600192505050600160005592915050565b6000828260405160200180836001600160a01b031660601b8152601401828152602001925050506040516020818303038152906040528051906020012090505b92915050565b60116020526000908152604090205481565b60095481565b60045481565b612a8061470b565b6001600160a01b0316612a91612b24565b6001600160a01b031614612ada576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b6001546001600160a01b031690565b69d3c21bcecceda100000081565b600081815260126020908152604080832081516101808101835281546001600160a01b031681526001820180548451818702810187019095528085526060969592948584019390929190830182828015612bc457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612ba6575b505050918352505060028201546001600160a01b0316602080830191909152600383015460408301526004830154606083015260058301546080830152600683015460ff908116151560a0840152600784015460c0840152600884015460e08401526009840154610100840152600a840154610120840152600b9093015490921615156101409091015201519392505050565b60086020526000908152604090205481565b60055481565b3360009081526010602052604090205460ff16612cbd5760405162461bcd60e51b8152600401808060200182810382526031815260200180615cdb6031913960400191505060405180910390fd5b600e54600c54808210612cd1575050612e48565b80841115612cdd578093505b83821015612e43576000600c8381548110612cf457fe5b90600052602060002001549050306001600160a01b03166327b42c0f82866040518363ffffffff1660e01b815260040180838152602001826001600160a01b0316815260200192505050602060405180830381600087803b158015612d5857600080fd5b505af1925050508015612d7d57506040513d6020811015612d7857600080fd5b505160015b612e11576040805163225fc9fd60e01b8152600481018390526001600160a01b03861660248201529051309163225fc9fd9160448083019260209291908290030181600087803b158015612dd057600080fd5b505af1925050508015612df557506040513d6020811015612df057600080fd5b505160015b612dfe57612e0c565b80612e0a575050612e43565b505b612e1f565b80612e1d575050612e43565b505b600c8381548110612e2c57fe5b600091825260208220015550600190910190612cdd565b50600e555b5050565b600e5481565b612e5a61470b565b6001600160a01b0316612e6b612b24565b6001600160a01b031614612eb4576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b600a821115612ef45760405162461bcd60e51b815260040180806020018281038252602f815260200180615a42602f913960400191505060405180910390fd5b610e10811115612f355760405162461bcd60e51b81526004018080602001828103825260288152602001806159b36028913960400191505060405180910390fd5b600a829055600b819055604080518381526020810183905281517f99405003edcc25c06db454f63e8b4d88ffdb950af2cb867050c4c0c89b8ff5ec929181900390910190a15050565b606481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600b5481565b60026000541415612ff3576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b60026000556009548110156130395760405162461bcd60e51b81526004018080602001828103825260248152602001806159286024913960400191505060405180910390fd5b8034146130775760405162461bcd60e51b815260040180806020018281038252602181526020018061596c6021913960400191505060405180910390fd5b875160011480613088575087516002145b6130c35760405162461bcd60e51b8152600401808060200182810382526024815260200180615a716024913960400191505060405180910390fd5b6130cb614300565b85156131ff577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0f479a16040518163ffffffff1660e01b815260040160206040518083038186803b15801561312a57600080fd5b505afa15801561313e573d6000803e3d6000fd5b505050506040513d602081101561315457600080fd5b505188516001600160a01b0390911690631b827878908a9060009061317557fe5b602002602001015133308a6040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160a01b03168152602001828152602001945050505050600060405180830381600087803b1580156131e657600080fd5b505af11580156131fa573d6000803e3d6000fd5b505050505b6117b6338989898989898989600061437d565b600a81565b6002600054141561325d576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b60026000556009548210156132a35760405162461bcd60e51b81526004018080602001828103825260248152602001806159286024913960400191505060405180910390fd5b8134146132e15760405162461bcd60e51b815260040180806020018281038252602181526020018061596c6021913960400191505060405180910390fd5b8951600114806132f2575089516002145b61332d5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a716024913960400191505060405180910390fd5b80156133d0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a60018c51038151811061336d57fe5b60200260200101516001600160a01b0316146133d0576040805162461bcd60e51b815260206004820152601d60248201527f506f736974696f6e526f757465723a20696e76616c6964205f70617468000000604482015290519081900360640190fd5b6133d8614300565b6133eb338b8b8b8b8b8b8b8b8b8b614ddc565b505060016000555050505050505050565b61025881565b610e1081565b61341061470b565b6001600160a01b0316613421612b24565b6001600160a01b03161461346a576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b60005b835181101561350557600084828151811061348457fe5b6020026020010151905083828151811061349a57fe5b602002602001015160076000836001600160a01b03166001600160a01b03168152602001908152602001600020819055508282815181106134d757fe5b6020908102919091018101516001600160a01b0390921660009081526008909152604090205560010161346d565b507fae32d569b058895b9620d6552b09aaffedc9a6f396be4d595a224ad09f8b213983838360405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561357257818101518382015260200161355a565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156135b1578181015183820152602001613599565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156135f05781810151838201526020016135d8565b50505050905001965050505050505060405180910390a1505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663028d27d86040518163ffffffff1660e01b815260040160206040518083038186803b15801561366557600080fd5b505afa158015613679573d6000803e3d6000fd5b505050506040513d602081101561368f57600080fd5b50516001600160a01b031633146136d75760405162461bcd60e51b8152600401808060200182810382526036815260200180615d2f6036913960400191505060405180910390fd5b6001600160a01b038216600090815260066020526040902054806136fb5750612e48565b6001600160a01b03831660008181526006602052604081205561371f908383614009565b604080516001600160a01b0380861682528416602082015280820183905290517f4f1b51dd7a2fcb861aa2670f668be66835c4ee12b4bbbf037e4d0018f39819e49181900360600190a1505050565b600e54600c54600f54600d5490919293565b61378861470b565b6001600160a01b0316613799612b24565b6001600160a01b0316146137e2576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b6001600160a01b0381166138275760405162461bcd60e51b815260040180806020018281038252602681526020018061598d6026913960400191505060405180910390fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b3360009081526010602052604090205460ff166138d15760405162461bcd60e51b8152600401808060200182810382526031815260200180615cdb6031913960400191505060405180910390fd5b600f54600d548082106138e5575050612e48565b808411156138f1578093505b83821015613a57576000600d838154811061390857fe5b90600052602060002001549050306001600160a01b0316630d4d003d82866040518363ffffffff1660e01b815260040180838152602001826001600160a01b0316815260200192505050602060405180830381600087803b15801561396c57600080fd5b505af192505050801561399157506040513d602081101561398c57600080fd5b505160015b613a255760408051633051b17160e11b8152600481018390526001600160a01b0386166024820152905130916360a362e29160448083019260209291908290030181600087803b1580156139e457600080fd5b505af1925050508015613a0957506040513d6020811015613a0457600080fd5b505160015b613a1257613a20565b80613a1e575050613a57565b505b613a33565b80613a31575050613a57565b505b600d8381548110613a4057fe5b6000918252602082200155506001909101906138f1565b50600f555050565b60136020526000908152604090205481565b6012602052600090815260409020805460028201546003830154600484015460058501546006860154600787015460088801546009890154600a8a0154600b909a01546001600160a01b03998a169a999098169896979596949560ff94851695939492939192168b565b613ae361470b565b6001600160a01b0316613af4612b24565b6001600160a01b031614613b3d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b69d3c21bcecceda1000000811115613b865760405162461bcd60e51b815260040180806020018281038252602b815260200180615bc4602b913960400191505060405180910390fd5b60098190556040805182815290517f52a8358457e20bbb36e4086b83fb0749599f1893fe4c35a876c46dc4886d12db9181900360200190a150565b6000613bd8600b548461510c90919063ffffffff16565b4210613c155760405162461bcd60e51b8152600401808060200182810382526023815260200180615d0c6023913960400191505060405180910390fd5b613c2084848461464d565b90505b9392505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b158015613c8657600080fd5b505afa158015613c9a573d6000803e3d6000fd5b505050506040513d6020811015613cb057600080fd5b5051604080516303b6b4bb60e51b81526001600160a01b038b8116600483015288156024830152915191909216916376d69760916044808301926020929190829003018186803b158015613d0357600080fd5b505afa158015613d17573d6000803e3d6000fd5b505050506040513d6020811015613d2d57600080fd5b505190508415613d7b5782811015613d765760405162461bcd60e51b8152600401808060200182810382526030815260200180615a956030913960400191505060405180910390fd5b613dba565b82811115613dba5760405162461bcd60e51b8152600401808060200182810382526031815260200180615b936031913960400191505060405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630af785596040518163ffffffff1660e01b815260040160206040518083038186803b158015613e1357600080fd5b505afa158015613e27573d6000803e3d6000fd5b505050506040513d6020811015613e3d57600080fd5b505160408051633cc8e33b60e21b81526001600160a01b038d811660048301528c811660248301528b811660448301528815156064830152608482018a905260a48201859052600060c48301819052925193169263f3238cec9260e48084019391929182900301818387803b158015613eb557600080fd5b505af1158015613ec9573d6000803e3d6000fd5b5050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0f479a16040518163ffffffff1660e01b815260040160206040518083038186803b158015613f2857600080fd5b505afa158015613f3c573d6000803e3d6000fd5b505050506040513d6020811015613f5257600080fd5b505160408051632662166b60e01b81526001600160a01b038e811660048301528d811660248301528c81166044830152606482018c9052608482018b905289151560a483015288811660c483015291519190921691632662166b9160e48083019260209291908290030181600087803b158015613fce57600080fd5b505af1158015613fe2573d6000803e3d6000fd5b505050506040513d6020811015613ff857600080fd5b50519b9a5050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261405b908490615166565b505050565b60008351600214156140a7576140a08460008151811061407c57fe5b60200260200101518560018151811061409157fe5b60200260200101518585615217565b9050613c23565b60405162461bcd60e51b8152600401808060200182810382526029815260200180615c296029913960400191505060405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000009050806001600160a01b0316632e1a7d4d846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561414957600080fd5b505af115801561415d573d6000803e3d6000fd5b5050600254604051600093506001600160a01b0386169250869084818181858888f193505050503d80600081146141b0576040519150601f19603f3d011682016040523d82523d6000602084013e6141b5565b606091505b5050905080156141c6575050612e48565b816001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561420157600080fd5b505af1158015614215573d6000803e3d6000fd5b5050505050816001600160a01b031663a9059cbb84866040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561427157600080fd5b505af1158015614285573d6000803e3d6000fd5b505050506040513d602081101561429b57600080fd5b505050505050565b6000828211156142fa576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b341561437b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561436157600080fd5b505af1158015614375573d6000803e3d6000fd5b50505050505b565b6001600160a01b038a166000908152601160205260408120546143a190600161510c565b6001600160a01b03808d1660008181526011602090815260408083208690558051610180810182529384529083018f9052928d1692820192909252606081018b9052608081018a905260a0810189905287151560c082015260e081018790526101008101869052436101208201524261014082015284151561016082015291925061442c8d84612a14565b6000818152601260209081526040909120845181546001600160a01b0319166001600160a01b03909116178155848201518051939450859391926144789260018501929091019061587f565b5060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a81548160ff02191690831515021790555060e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160006101000a81548160ff021916908315150217905550905050600c8190806001815401808255809150506001900390600052602060002001600090919091909150558c6001600160a01b03167fa89f00a1c1cd0de066abac1a05f9314520fef2a9b98f6a99ff4548ed1161c03c8d8d8d8d8d8d8d8d8c43423a60405180806020018d6001600160a01b031681526020018c81526020018b81526020018a8152602001891515815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528e818151815260200191508051906020019060200280838360005b83811015614620578181015183820152602001614608565b505050509050019d505050505050505050505050505060405180910390a250505050505050505050505050565b3360009081526010602052604081205460ff1615614684574361467b600a548661510c90919063ffffffff16565b11159050613c23565b336001600160a01b0383161480156146b05750426146ad6003548561510c90919063ffffffff16565b11155b614701576040805162461bcd60e51b815260206004820152601960248201527f506f736974696f6e526f757465723a20666f7262696464656e00000000000000604482015290519081900360640190fd5b5060019392505050565b3390565b600080614720888888888888615371565b905080156147df57600061475761271061475161474a6004546127106142a390919063ffffffff16565b8a906155cf565b90615628565b9050600061476588836142a3565b905060008960018b51038151811061477957fe5b602002602001015190506147bb8260066000846001600160a01b03166001600160a01b031681526020019081526020016000205461510c90919063ffffffff16565b6001600160a01b039091166000908152600660205260409020555091506147e49050565b859150505b9695505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561484957600080fd5b505afa15801561485d573d6000803e3d6000fd5b505050506040513d602081101561487357600080fd5b505160408051631f94a27560e31b815290519192506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163fca513a8916004808301926020929190829003018186803b1580156148db57600080fd5b505afa1580156148ef573d6000803e3d6000fd5b505050506040513d602081101561490557600080fd5b5051604080516303b6b4bb60e51b81526001600160a01b0389811660048301528715156024830152915191909216916376d69760916044808301926020929190829003018186803b15801561495957600080fd5b505afa15801561496d573d6000803e3d6000fd5b505050506040513d602081101561498357600080fd5b5051905083156149d157828111156149cc5760405162461bcd60e51b8152600401808060200182810382526031815260200180615b936031913960400191505060405180910390fd5b614a10565b82811015614a105760405162461bcd60e51b8152600401808060200182810382526030815260200180615a956030913960400191505060405180910390fd5b8315614b01576001600160a01b0386166000908152600760205260409020548015801590614abf575080614abd87856001600160a01b031663f07456ce8b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015614a8b57600080fd5b505afa158015614a9f573d6000803e3d6000fd5b505050506040513d6020811015614ab557600080fd5b50519061510c565b115b15614afb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806158fa602e913960400191505060405180910390fd5b50614bb6565b6001600160a01b0386166000908152600860205260409020548015801590614b78575080614b7687856001600160a01b0316638a78daa88b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015614a8b57600080fd5b115b15614bb45760405162461bcd60e51b815260040180806020018281038252602f815260200180615af0602f913960400191505060405180910390fd5b505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630af785596040518163ffffffff1660e01b815260040160206040518083038186803b158015614c0f57600080fd5b505afa158015614c23573d6000803e3d6000fd5b505050506040513d6020811015614c3957600080fd5b505160408051633cc8e33b60e21b81526001600160a01b038b811660048301528a81166024830152898116604483015287151560648301526084820189905260a48201859052600160c48301529151919092169163f3238cec9160e480830192600092919082900301818387803b158015614cb357600080fd5b505af1158015614cc7573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0f479a16040518163ffffffff1660e01b815260040160206040518083038186803b158015614d2457600080fd5b505afa158015614d38573d6000803e3d6000fd5b505050506040513d6020811015614d4e57600080fd5b505160408051630f8ee8bb60e11b81526001600160a01b038b811660048301528a81166024830152898116604483015260648201899052871515608483015291519190921691631f1dd1769160a480830192600092919082900301818387803b158015614dba57600080fd5b505af1158015614dce573d6000803e3d6000fd5b505050505050505050505050565b6001600160a01b038b16600090815260136020526040812054614e0090600161510c565b905080601360008e6001600160a01b03166001600160a01b03168152602001908152602001600020819055506000604051806101a001604052808e6001600160a01b031681526020018d81526020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200143815260200142815260200184151581525090506000614eb38e84612a14565b6000818152601460209081526040909120845181546001600160a01b0319166001600160a01b0390911617815584820151805193945085939192614eff9260018501929091019061587f565b5060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff02191690831515021790555060c08201518160050160016101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e0820151816006015561010082015181600701556101208201518160080155610140820151816009015561016082015181600a015561018082015181600b0160006101000a81548160ff021916908315150217905550905050600d8190806001815401808255809150506001900390600052602060002001600090919091909150558d6001600160a01b03167f506f2634e4508d88b04b7511af75c6d4c29b2b6f4f5067676b9400b28f3761d28e8e8e8e8e8e8e8e8e8d434260405180806020018d6001600160a01b031681526020018c81526020018b81526020018a15158152602001896001600160a01b0316815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528e818151815260200191508051906020019060200280838360005b838110156150de5781810151838201526020016150c6565b505050509050019d505050505050505050505050505060405180910390a25050505050505050505050505050565b600082820183811015613c23576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006151bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661568f9092919063ffffffff16565b80519091501561405b578080602001905160208110156151da57600080fd5b505161405b5760405162461bcd60e51b815260040180806020018281038252602a815260200180615cb1602a913960400191505060405180910390fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561527357600080fd5b505afa158015615287573d6000803e3d6000fd5b505050506040513d602081101561529d57600080fd5b505160408051634998b10960e11b81526001600160a01b038981166004830152888116602483015286811660448301529151919092169163933162129160648083019260209291908290030181600087803b1580156152fb57600080fd5b505af115801561530f573d6000803e3d6000fd5b505050506040513d602081101561532557600080fd5b50519050838110156153685760405162461bcd60e51b815260040180806020018281038252602b8152602001806159db602b913960400191505060405180910390fd5b95945050505050565b600082615380575060006147e4565b8161538d575060016147e4565b60008660018851038151811061539f57fe5b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561540457600080fd5b505afa158015615418573d6000803e3d6000fd5b505050506040513d602081101561542e57600080fd5b505160408051634a3f088d60e01b81526001600160a01b038c8116600483015285811660248301528981166044830152881515606483015291519293506000928392851691634a3f088d91608480830192610100929190829003018186803b15801561549957600080fd5b505afa1580156154ad573d6000803e3d6000fd5b505050506040513d6101008110156154c457600080fd5b5080516020909101519092509050816154e45760009450505050506147e4565b60006154f0838861510c565b90506000846001600160a01b0316630a48d5a9878d6040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561554957600080fd5b505afa15801561555d573d6000803e3d6000fd5b505050506040513d602081101561557357600080fd5b505190506000615583848361510c565b9050600061559785614751886127106155cf565b905060006155b88361475160055461271001886155cf90919063ffffffff16565b919091109f9e505050505050505050505050505050565b6000826155de57506000612a54565b828202828482816155eb57fe5b0414613c235760405162461bcd60e51b8152600401808060200182810382526021815260200180615b526021913960400191505060405180910390fd5b600080821161567e576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161568757fe5b049392505050565b6060613c208484600085856156a3856157b4565b6156f4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b602083106157325780518252601f199092019160209182019101615713565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114615794576040519150601f19603f3d011682016040523d82523d6000602084013e615799565b606091505b50915091506157a98282866157ba565b979650505050505050565b3b151590565b606083156157c9575081613c23565b8251156157d95782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561582357818101518382015260200161580b565b50505050905090810190601f1680156158505780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508054600082559060005260206000209081019061587c91906158e4565b50565b8280548282559060005260206000209081019282156158d4579160200282015b828111156158d457825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061589f565b506158e09291506158e4565b5090565b5b808211156158e057600081556001016158e556fe42617365506f736974696f6e4d616e616765723a206d617820676c6f62616c206c6f6e6773206578636565646564506f736974696f6e526f757465723a20696e76616c696420657865637574696f6e4665655265656e7472616e637947756172643a207265656e7472616e742063616c6c00506f736974696f6e526f757465723a20696e76616c6964206d73672e76616c75654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373506f736974696f6e526f757465723a206d617854696d6544656c617920697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e73756666696369656e7420616d6f756e744f7574506f736974696f6e526f757465723a20696e637265617365506f736974696f6e526571756573744b657973537461727420697320746f6f2068696768506f736974696f6e526f757465723a206d696e426c6f636b44656c61794b656570657220697320746f6f2068696768506f736974696f6e526f757465723a20696e76616c6964205f70617468206c656e67746842617365506f736974696f6e4d616e616765723a206d61726b207072696365206c6f776572207468616e206c696d697442617365506f736974696f6e4d616e616765723a206465706f73697446656520697320746f6f206869676842617365506f736974696f6e4d616e616765723a206d617820676c6f62616c2073686f72747320657863656564656442617365506f736974696f6e4d616e616765723a206d696e54696d6544656c61795075626c696320697320746f6f2068696768536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657242617365506f736974696f6e4d616e616765723a206d61726b20707269636520686967686572207468616e206c696d6974506f736974696f6e526f757465723a206d696e457865637574696f6e46656520697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e637265617365506f736974696f6e42756666657242707320697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e76616c6964205f706174682e6c656e677468506f736974696f6e526f757465723a206465637265617365506f736974696f6e526571756573744b657973537461727420697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e76616c69642073656e6465725361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564506f736974696f6e526f757465723a2063616c6c6572206973206e6f742074686520706f736974696f6e206b6565706572506f736974696f6e526f757465723a207265717565737420686173206578706972656442617365506f736974696f6e4d616e616765723a204f6e6c792050686c704d616e616765722063616e20776974686472617720666565a26469706673582212207461fa329d0fcdc8200d8c5a8143ee7e08bbd41bd405e9acea33174ad69f5ca764736f6c6343000706003342617365506f736974696f6e4d616e616765723a2077657468206973207a65726f206164647265737342617365506f736974696f6e4d616e616765723a2061646472657373657350726f7669646572206973207a65726f206164647265737342617365506f736974696f6e4d616e616765723a206465706f73697446656520697320746f6f2068696768506f736974696f6e526f757465723a206d696e457865637574696f6e46656520697320746f6f2068696768000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a27000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000a2a15d09519be00000

Deployed ByteCode

0x6080604052600436106103395760003560e01c806363ae2103116101ab578063cb0269c9116100f7578063f255527811610095578063f3883d8b1161006f578063f3883d8b14610f8f578063fa44457714610fc8578063faf990f314610ffb578063fc2cee6214611089576103a7565b8063f255527814610ee6578063f2cea6a514610f21578063f2fde38b14610f5c576103a7565b8063e70dd2fc116100d1578063e70dd2fc14610c28578063e8caee1c14610d0a578063ec2a1bf214610d1f578063ef12c67e14610d34576103a7565b8063cb0269c914610b2e578063ceed2cc114610b43578063d467a4ae14610c13576103a7565b80639698d25a116101645780639b5786201161013e5780639b57862014610abf578063a4e7684f14610ad4578063c6d87dd514610b04578063c72c4d1014610b19576103a7565b80639698d25a14610a3e57806398d1e03a14610a715780639a20810014610a86576103a7565b806363ae2103146109ab57806367a52793146109c0578063715018a6146109d55780638da5cb5b146109ea5780638f649494146109ff57806395e9bbd714610a14576103a7565b80632d79cf42116102855780634278555f116102235780635d5c22e8116101fd5780635d5c22e81461088c57806360a362e21461090657806362f8a3fe1461093f578063633451de14610978576103a7565b80634278555f14610823578063490ae2101461084d5780635841fcaa14610877576103a7565b806336eba48a1161025f57806336eba48a146107805780633a2a80c7146107b35780633a9b52ad146107c85780633fc8cef3146107f2576103a7565b80632d79cf4214610700578063308aa81f146107155780633422ead114610745576103a7565b80631bca8cf0116102f2578063225fc9fd116102cc578063225fc9fd1461063a578063233bfe3b1461067357806327b42c0f1461069d5780632b73fb18146106d6576103a7565b80631bca8cf0146105465780631ce9cb8f1461055b5780631f2851061461058e576103a7565b806304225954146103ac5780630d4d003d146103e85780631045c74e14610435578063126082cf14610468578063133e5b171461047d57806315de638614610468576103a7565b366103a757336001600160a01b037f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a2716146103a55760405162461bcd60e51b8152600401808060200182810382526023815260200180615c8e6023913960400191505060405180910390fd5b005b600080fd5b3480156103b857600080fd5b506103d6600480360360208110156103cf57600080fd5b50356110b3565b60408051918252519081900360200190f35b3480156103f457600080fd5b506104216004803603604081101561040b57600080fd5b50803590602001356001600160a01b03166110d4565b604080519115158252519081900360200190f35b34801561044157600080fd5b506103d66004803603602081101561045857600080fd5b50356001600160a01b03166115c4565b34801561047457600080fd5b506103d66115d6565b6103a5600480360360e081101561049357600080fd5b810190602081018135600160201b8111156104ad57600080fd5b8201836020820111156104bf57600080fd5b803590602001918460208302840111600160201b831117156104e057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b0383351693505050602081013590604081013590606081013515159060808101359060a001356115dc565b34801561055257600080fd5b506103d66117c5565b34801561056757600080fd5b506103d66004803603602081101561057e57600080fd5b50356001600160a01b03166117cb565b34801561059a57600080fd5b506105b8600480360360208110156105b157600080fd5b50356117dd565b604051808d6001600160a01b031681526020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200184815260200183815260200182151581526020019c5050505050505050505050505060405180910390f35b34801561064657600080fd5b506104216004803603604081101561065d57600080fd5b50803590602001356001600160a01b0316611849565b34801561067f57600080fd5b506103a56004803603602081101561069657600080fd5b5035611be9565b3480156106a957600080fd5b50610421600480360360408110156106c057600080fd5b50803590602001356001600160a01b0316611cc7565b3480156106e257600080fd5b506103a5600480360360208110156106f957600080fd5b50356120c8565b34801561070c57600080fd5b506103d66121a6565b34801561072157600080fd5b506103a56004803603604081101561073857600080fd5b50803590602001356121ac565b34801561075157600080fd5b506103a56004803603604081101561076857600080fd5b506001600160a01b03813516906020013515156122d9565b34801561078c57600080fd5b50610421600480360360208110156107a357600080fd5b50356001600160a01b031661239b565b3480156107bf57600080fd5b506103d66123b0565b3480156107d457600080fd5b506103a5600480360360208110156107eb57600080fd5b50356123b6565b3480156107fe57600080fd5b50610807612453565b604080516001600160a01b039092168252519081900360200190f35b34801561082f57600080fd5b506103d66004803603602081101561084657600080fd5b5035612477565b34801561085957600080fd5b506103a56004803603602081101561087057600080fd5b5035612487565b34801561088357600080fd5b506103d6612564565b34801561089857600080fd5b506108b6600480360360208110156108af57600080fd5b503561256a565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108f25781810151838201526020016108da565b505050509050019250505060405180910390f35b34801561091257600080fd5b506104216004803603604081101561092957600080fd5b50803590602001356001600160a01b031661268e565b34801561094b57600080fd5b506103d66004803603604081101561096257600080fd5b506001600160a01b038135169060200135612a14565b34801561098457600080fd5b506103d66004803603602081101561099b57600080fd5b50356001600160a01b0316612a5a565b3480156109b757600080fd5b506103d6612a6c565b3480156109cc57600080fd5b506103d6612a72565b3480156109e157600080fd5b506103a5612a78565b3480156109f657600080fd5b50610807612b24565b348015610a0b57600080fd5b506103d6612b33565b348015610a2057600080fd5b506108b660048036036020811015610a3757600080fd5b5035612b41565b348015610a4a57600080fd5b506103d660048036036020811015610a6157600080fd5b50356001600160a01b0316612c57565b348015610a7d57600080fd5b506103d6612c69565b348015610a9257600080fd5b506103a560048036036040811015610aa957600080fd5b50803590602001356001600160a01b0316612c6f565b348015610acb57600080fd5b506103d6612e4c565b348015610ae057600080fd5b506103a560048036036040811015610af757600080fd5b5080359060200135612e52565b348015610b1057600080fd5b506103d6612f7e565b348015610b2557600080fd5b50610807612f83565b348015610b3a57600080fd5b506103d6612fa7565b6103a56004803603610100811015610b5a57600080fd5b810190602081018135600160201b811115610b7457600080fd5b820183602082011115610b8657600080fd5b803590602001918460208302840111600160201b83111715610ba757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b0383351693505050602081013590604081013590606081013590608081013515159060a08101359060c00135612fad565b348015610c1f57600080fd5b506103d6613212565b6103a56004803603610140811015610c3f57600080fd5b810190602081018135600160201b811115610c5957600080fd5b820183602082011115610c6b57600080fd5b803590602001918460208302840111600160201b83111715610c8c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505081356001600160a01b0390811693506020830135926040810135925060608101351515916080820135169060a08101359060c08101359060e08101359061010001351515613217565b348015610d1657600080fd5b506103d66133fc565b348015610d2b57600080fd5b506103d6613402565b348015610d4057600080fd5b506103a560048036036060811015610d5757600080fd5b810190602081018135600160201b811115610d7157600080fd5b820183602082011115610d8357600080fd5b803590602001918460208302840111600160201b83111715610da457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610df357600080fd5b820183602082011115610e0557600080fd5b803590602001918460208302840111600160201b83111715610e2657600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610e7557600080fd5b820183602082011115610e8757600080fd5b803590602001918460208302840111600160201b83111715610ea857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613408945050505050565b348015610ef257600080fd5b506103a560048036036040811015610f0957600080fd5b506001600160a01b038135811691602001351661360c565b348015610f2d57600080fd5b50610f3661376e565b604080519485526020850193909352838301919091526060830152519081900360800190f35b348015610f6857600080fd5b506103a560048036036020811015610f7f57600080fd5b50356001600160a01b0316613780565b348015610f9b57600080fd5b506103a560048036036040811015610fb257600080fd5b50803590602001356001600160a01b0316613883565b348015610fd457600080fd5b506103d660048036036020811015610feb57600080fd5b50356001600160a01b0316613a5f565b34801561100757600080fd5b506110256004803603602081101561101e57600080fd5b5035613a71565b604080516001600160a01b039c8d1681529a909b1660208b0152898b01989098526060890196909652608088019490945291151560a087015260c086015260e085015261010084015261012083015215156101408201529051908190036101600190f35b34801561109557600080fd5b506103a5600480360360208110156110ac57600080fd5b5035613adb565b600c81815481106110c357600080fd5b600091825260209091200154905081565b60006002600054141561111c576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260146020908152604080832081516101a08101835281546001600160a01b0316815260018201805484518187028101870190955280855291949293858401939092908301828280156111a157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611183575b505050918352505060028201546001600160a01b0390811660208301526003830154604083015260048301546060830152600583015460ff8082161515608085015261010091829004831660a0850152600685015460c0850152600785015460e08501526008850154918401919091526009840154610120840152600a840154610140840152600b9093015490921615156101609091015281519192501661124d5760019150506115b9565b60006112688261014001518361016001518460000151613bc1565b90508061127a576000925050506115b9565b600085815260146020526040812080546001600160a01b0319168155906112a4600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820180546001600160a81b031916905560068201819055600782018190556008820181905560098201819055600a8201819055600b909101805460ff19169055825160208401518051611347929190849061132057fe5b60200260200101518560400151866060015187608001518860a00151308a60e00151613c2a565b9050801561146e576001836020015151111561142f576114187f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b1580156113b957600080fd5b505afa1580156113cd573d6000803e3d6000fd5b505050506040513d60208110156113e357600080fd5b5051602085015180518491906000906113f857fe5b60200260200101516001600160a01b03166140099092919063ffffffff16565b61142c836020015184610100015130614060565b90505b8261018001511561144d57611448818460c001516140de565b61146e565b61146e8360c00151828560200151600187602001515103815181106113f857fe5b61147d836101200151866140de565b82600001516001600160a01b03167f21435c5b618d77ff3657140cd3318e2cffaebc5e0e1b7318f56a9ba4044c3ed284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001518c61012001516114f38e6101400151436142a390919063ffffffff16565b6101608f01516115049042906142a3565b60405180806020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200184815260200183815260200182810382528d818151815260200191508051906020019060200280838360005b8381101561159457818101518382015260200161157c565b505050509050019c5050505050505050505050505060405180910390a2600193505050505b600160005592915050565b60076020526000908152604090205481565b61271081565b60026000541415611622576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b60026000556009548110156116685760405162461bcd60e51b81526004018080602001828103825260248152602001806159286024913960400191505060405180910390fd5b803410156116a75760405162461bcd60e51b815260040180806020018281038252602181526020018061596c6021913960400191505060405180910390fd5b8651600114806116b8575086516002145b6116f35760405162461bcd60e51b8152600401808060200182810382526024815260200180615a716024913960400191505060405180910390fd5b7f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a276001600160a01b03168760008151811061172a57fe5b60200260200101516001600160a01b03161461178d576040805162461bcd60e51b815260206004820152601d60248201527f506f736974696f6e526f757465723a20696e76616c6964205f70617468000000604482015290519081900360640190fd5b611795614300565b60006117a134836142a3565b90506117b6338989848a8a8a8a8a600161437d565b50506001600055505050505050565b600f5481565b60066020526000908152604090205481565b6014602052600090815260409020805460028201546003830154600484015460058501546006860154600787015460088801546009890154600a8a0154600b909a01546001600160a01b03998a169a988a16999798969760ff808816986101009098049091169691168c565b600060026000541415611891576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260126020908152604080832081516101808101835281546001600160a01b03168152600182018054845181870281018701909552808552919492938584019390929083018282801561191657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116118f8575b505050918352505060028201546001600160a01b039081166020830152600383015460408301526004830154606083015260058301546080830152600683015460ff908116151560a0840152600784015460c0840152600884015460e08401526009840154610100840152600a840154610120840152600b909301549092161515610140909101528151919250166119b25760019150506115b9565b60006119cd826101200151836101400151846000015161464d565b9050806119df576000925050506115b9565b600085815260126020526040812080546001600160a01b031916815590611a09600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820181905560068201805460ff19908116909155600783018290556008830182905560098301829055600a830191909155600b9091018054909116905561016082015115611a8d57611a88826060015183600001516140de565b611aab565b611aab8260000151836060015184602001516000815181106113f857fe5b611aba826101000151856140de565b81600001516001600160a01b03167f35b638e650e2328786fb405bd69d2083dbedc018d086662e74b775b4f1dae4bf83602001518460400151856060015186608001518760a001518860c001518960e001518a6101000151611b2a8c6101200151436142a390919063ffffffff16565b6101408d0151611b3b9042906142a3565b60405180806020018b6001600160a01b031681526020018a8152602001898152602001888152602001871515815260200186815260200185815260200184815260200183815260200182810382528c818151815260200191508051906020019060200280838360005b83811015611bbc578181015183820152602001611ba4565b505050509050019b50505050505050505050505060405180910390a2600192505050600160005592915050565b611bf161470b565b6001600160a01b0316611c02612b24565b6001600160a01b031614611c4b576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b612710811115611c8c5760405162461bcd60e51b815260040180806020018281038252603a815260200180615bef603a913960400191505060405180910390fd5b60058190556040805182815290517f21167d0d4661af93817ebce920f18986eed3d75d5e1c03f2aed05efcbafbc4529181900360200190a150565b600060026000541415611d0f576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260126020908152604080832081516101808101835281546001600160a01b031681526001820180548451818702810187019095528085529194929385840193909290830182828015611d9457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d76575b505050918352505060028201546001600160a01b039081166020830152600383015460408301526004830154606083015260058301546080830152600683015460ff908116151560a0840152600784015460c0840152600884015460e08401526009840154610100840152600a840154610120840152600b90930154909216151561014090910152815191925016611e305760019150506115b9565b6000611e4b8261012001518361014001518460000151613bc1565b905080611e5d576000925050506115b9565b600085815260126020526040812080546001600160a01b031916815590611e87600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820181905560068201805460ff19908116909155600783018290556008830182905560098301829055600a830191909155600b9091018054909116905560608201511561200b5760008260600151905060007f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5757600080fd5b505afa158015611f6b573d6000803e3d6000fd5b505050506040513d6020811015611f8157600080fd5b505160208501515190915060011015611fc457611fae81856060015186602001516000815181106113f857fe5b611fc18460200151856080015130614060565b91505b6000611fe8856000015186602001518588604001518960c001518a60a0015161470f565b905061200782828760200151600189602001515103815181106113f857fe5b5050505b815160208301518051612049929190600019810190811061202857fe5b602002602001015184604001518560a001518660c001518760e001516147ee565b612058826101000151856140de565b81600001516001600160a01b03167f1be316b94d38c07bd41cdb4913772d0a0a82802786a2f8b657b6e85dbcdfc64183602001518460400151856060015186608001518760a001518860c001518960e001518a6101000151611b2a8c6101200151436142a390919063ffffffff16565b6120d061470b565b6001600160a01b03166120e1612b24565b6001600160a01b03161461212a576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b61025881111561216b5760405162461bcd60e51b8152600401808060200182810382526033815260200180615b1f6033913960400191505060405180910390fd5b60038190556040805182815290517fbd7411e312e9c7c95b6798503250129c3b613975a11dc36e76f469c5b8e8bcd59181900360200190a150565b60025481565b6121b461470b565b6001600160a01b03166121c5612b24565b6001600160a01b03161461220e576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b600c5482111561224f5760405162461bcd60e51b815260040180806020018281038252603c815260200180615a06603c913960400191505060405180910390fd5b600d548111156122905760405162461bcd60e51b815260040180806020018281038252603c815260200180615c52603c913960400191505060405180910390fd5b600e829055600f819055604080518381526020810183905281517febb0f666150f4be5b60c45df8f3e49992510b0128027fe58eea6110f296493bc929181900390910190a15050565b6122e161470b565b6001600160a01b03166122f2612b24565b6001600160a01b03161461233b576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b6001600160a01b038216600081815260106020908152604091829020805460ff1916851515908117909155825190815291517ffbabc02389290a451c6e600d05bf9887b99bfad39d8e1237e4e3df042e4941fe9281900390910190a25050565b60106020526000908152604090205460ff1681565b60035481565b6123be61470b565b6001600160a01b03166123cf612b24565b6001600160a01b031614612418576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b60028190556040805182815290517f4d371d598d3a13f99ce992a17975bbaf1e1c256e072ec7d2f93ce88e40d9ba1c9181900360200190a150565b7f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a2781565b600d81815481106110c357600080fd5b61248f61470b565b6001600160a01b03166124a0612b24565b6001600160a01b0316146124e9576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b60648111156125295760405162461bcd60e51b815260040180806020018281038252602b815260200180615ac5602b913960400191505060405180910390fd5b60048190556040805182815290517f974fd3c1fcb4653dfc4fb740c4c692cd212d55c28f163f310128cb64d83006759181900360200190a150565b600a5481565b600081815260146020908152604080832081516101a08101835281546001600160a01b0316815260018201805484518187028101870190955280855260609695929485840193909291908301828280156125ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116125cf575b505050918352505060028201546001600160a01b039081166020808401919091526003840154604084015260048401546060840152600584015460ff808216151560808601526101009182900490931660a0850152600685015460c0850152600785015460e08501526008850154908401526009840154610120840152600a840154610140840152600b909301541615156101609091015201519392505050565b6000600260005414156126d6576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b6002600090815583815260146020908152604080832081516101a08101835281546001600160a01b03168152600182018054845181870281018701909552808552919492938584019390929083018282801561275b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161273d575b505050918352505060028201546001600160a01b0390811660208301526003830154604083015260048301546060830152600583015460ff8082161515608085015261010091829004831660a0850152600685015460c0850152600785015460e08501526008850154918401919091526009840154610120840152600a840154610140840152600b909301549092161515610160909101528151919250166128075760019150506115b9565b6000612822826101400151836101600151846000015161464d565b905080612834576000925050506115b9565b600085815260146020526040812080546001600160a01b03191681559061285e600183018261585e565b506002810180546001600160a01b0319169055600060038201819055600482018190556005820180546001600160a81b031916905560068201819055600782018190556008820181905560098201819055600a820155600b01805460ff191690556101208201516128cf90856140de565b81600001516001600160a01b03167f87abfd78e844f28318363bdf3da99eab2f4a2da9ff7ae365484507f7b6c3f80583602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001516129458d6101400151436142a390919063ffffffff16565b6101608e01516129569042906142a3565b60405180806020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200184815260200183815260200182810382528d818151815260200191508051906020019060200280838360005b838110156129e65781810151838201526020016129ce565b505050509050019c5050505050505050505050505060405180910390a2600192505050600160005592915050565b6000828260405160200180836001600160a01b031660601b8152601401828152602001925050506040516020818303038152906040528051906020012090505b92915050565b60116020526000908152604090205481565b60095481565b60045481565b612a8061470b565b6001600160a01b0316612a91612b24565b6001600160a01b031614612ada576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b6001546001600160a01b031690565b69d3c21bcecceda100000081565b600081815260126020908152604080832081516101808101835281546001600160a01b031681526001820180548451818702810187019095528085526060969592948584019390929190830182828015612bc457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612ba6575b505050918352505060028201546001600160a01b0316602080830191909152600383015460408301526004830154606083015260058301546080830152600683015460ff908116151560a0840152600784015460c0840152600884015460e08401526009840154610100840152600a840154610120840152600b9093015490921615156101409091015201519392505050565b60086020526000908152604090205481565b60055481565b3360009081526010602052604090205460ff16612cbd5760405162461bcd60e51b8152600401808060200182810382526031815260200180615cdb6031913960400191505060405180910390fd5b600e54600c54808210612cd1575050612e48565b80841115612cdd578093505b83821015612e43576000600c8381548110612cf457fe5b90600052602060002001549050306001600160a01b03166327b42c0f82866040518363ffffffff1660e01b815260040180838152602001826001600160a01b0316815260200192505050602060405180830381600087803b158015612d5857600080fd5b505af1925050508015612d7d57506040513d6020811015612d7857600080fd5b505160015b612e11576040805163225fc9fd60e01b8152600481018390526001600160a01b03861660248201529051309163225fc9fd9160448083019260209291908290030181600087803b158015612dd057600080fd5b505af1925050508015612df557506040513d6020811015612df057600080fd5b505160015b612dfe57612e0c565b80612e0a575050612e43565b505b612e1f565b80612e1d575050612e43565b505b600c8381548110612e2c57fe5b600091825260208220015550600190910190612cdd565b50600e555b5050565b600e5481565b612e5a61470b565b6001600160a01b0316612e6b612b24565b6001600160a01b031614612eb4576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b600a821115612ef45760405162461bcd60e51b815260040180806020018281038252602f815260200180615a42602f913960400191505060405180910390fd5b610e10811115612f355760405162461bcd60e51b81526004018080602001828103825260288152602001806159b36028913960400191505060405180910390fd5b600a829055600b819055604080518381526020810183905281517f99405003edcc25c06db454f63e8b4d88ffdb950af2cb867050c4c0c89b8ff5ec929181900390910190a15050565b606481565b7f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c81565b600b5481565b60026000541415612ff3576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b60026000556009548110156130395760405162461bcd60e51b81526004018080602001828103825260248152602001806159286024913960400191505060405180910390fd5b8034146130775760405162461bcd60e51b815260040180806020018281038252602181526020018061596c6021913960400191505060405180910390fd5b875160011480613088575087516002145b6130c35760405162461bcd60e51b8152600401808060200182810382526024815260200180615a716024913960400191505060405180910390fd5b6130cb614300565b85156131ff577f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b031663b0f479a16040518163ffffffff1660e01b815260040160206040518083038186803b15801561312a57600080fd5b505afa15801561313e573d6000803e3d6000fd5b505050506040513d602081101561315457600080fd5b505188516001600160a01b0390911690631b827878908a9060009061317557fe5b602002602001015133308a6040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160a01b03168152602001828152602001945050505050600060405180830381600087803b1580156131e657600080fd5b505af11580156131fa573d6000803e3d6000fd5b505050505b6117b6338989898989898989600061437d565b600a81565b6002600054141561325d576040805162461bcd60e51b815260206004820152601f602482015260008051602061594c833981519152604482015290519081900360640190fd5b60026000556009548210156132a35760405162461bcd60e51b81526004018080602001828103825260248152602001806159286024913960400191505060405180910390fd5b8134146132e15760405162461bcd60e51b815260040180806020018281038252602181526020018061596c6021913960400191505060405180910390fd5b8951600114806132f2575089516002145b61332d5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a716024913960400191505060405180910390fd5b80156133d0577f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a276001600160a01b03168a60018c51038151811061336d57fe5b60200260200101516001600160a01b0316146133d0576040805162461bcd60e51b815260206004820152601d60248201527f506f736974696f6e526f757465723a20696e76616c6964205f70617468000000604482015290519081900360640190fd5b6133d8614300565b6133eb338b8b8b8b8b8b8b8b8b8b614ddc565b505060016000555050505050505050565b61025881565b610e1081565b61341061470b565b6001600160a01b0316613421612b24565b6001600160a01b03161461346a576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b60005b835181101561350557600084828151811061348457fe5b6020026020010151905083828151811061349a57fe5b602002602001015160076000836001600160a01b03166001600160a01b03168152602001908152602001600020819055508282815181106134d757fe5b6020908102919091018101516001600160a01b0390921660009081526008909152604090205560010161346d565b507fae32d569b058895b9620d6552b09aaffedc9a6f396be4d595a224ad09f8b213983838360405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561357257818101518382015260200161355a565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156135b1578181015183820152602001613599565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156135f05781810151838201526020016135d8565b50505050905001965050505050505060405180910390a1505050565b7f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b031663028d27d86040518163ffffffff1660e01b815260040160206040518083038186803b15801561366557600080fd5b505afa158015613679573d6000803e3d6000fd5b505050506040513d602081101561368f57600080fd5b50516001600160a01b031633146136d75760405162461bcd60e51b8152600401808060200182810382526036815260200180615d2f6036913960400191505060405180910390fd5b6001600160a01b038216600090815260066020526040902054806136fb5750612e48565b6001600160a01b03831660008181526006602052604081205561371f908383614009565b604080516001600160a01b0380861682528416602082015280820183905290517f4f1b51dd7a2fcb861aa2670f668be66835c4ee12b4bbbf037e4d0018f39819e49181900360600190a1505050565b600e54600c54600f54600d5490919293565b61378861470b565b6001600160a01b0316613799612b24565b6001600160a01b0316146137e2576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b6001600160a01b0381166138275760405162461bcd60e51b815260040180806020018281038252602681526020018061598d6026913960400191505060405180910390fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b3360009081526010602052604090205460ff166138d15760405162461bcd60e51b8152600401808060200182810382526031815260200180615cdb6031913960400191505060405180910390fd5b600f54600d548082106138e5575050612e48565b808411156138f1578093505b83821015613a57576000600d838154811061390857fe5b90600052602060002001549050306001600160a01b0316630d4d003d82866040518363ffffffff1660e01b815260040180838152602001826001600160a01b0316815260200192505050602060405180830381600087803b15801561396c57600080fd5b505af192505050801561399157506040513d602081101561398c57600080fd5b505160015b613a255760408051633051b17160e11b8152600481018390526001600160a01b0386166024820152905130916360a362e29160448083019260209291908290030181600087803b1580156139e457600080fd5b505af1925050508015613a0957506040513d6020811015613a0457600080fd5b505160015b613a1257613a20565b80613a1e575050613a57565b505b613a33565b80613a31575050613a57565b505b600d8381548110613a4057fe5b6000918252602082200155506001909101906138f1565b50600f555050565b60136020526000908152604090205481565b6012602052600090815260409020805460028201546003830154600484015460058501546006860154600787015460088801546009890154600a8a0154600b909a01546001600160a01b03998a169a999098169896979596949560ff94851695939492939192168b565b613ae361470b565b6001600160a01b0316613af4612b24565b6001600160a01b031614613b3d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b73833981519152604482015290519081900360640190fd5b69d3c21bcecceda1000000811115613b865760405162461bcd60e51b815260040180806020018281038252602b815260200180615bc4602b913960400191505060405180910390fd5b60098190556040805182815290517f52a8358457e20bbb36e4086b83fb0749599f1893fe4c35a876c46dc4886d12db9181900360200190a150565b6000613bd8600b548461510c90919063ffffffff16565b4210613c155760405162461bcd60e51b8152600401808060200182810382526023815260200180615d0c6023913960400191505060405180910390fd5b613c2084848461464d565b90505b9392505050565b6000807f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b158015613c8657600080fd5b505afa158015613c9a573d6000803e3d6000fd5b505050506040513d6020811015613cb057600080fd5b5051604080516303b6b4bb60e51b81526001600160a01b038b8116600483015288156024830152915191909216916376d69760916044808301926020929190829003018186803b158015613d0357600080fd5b505afa158015613d17573d6000803e3d6000fd5b505050506040513d6020811015613d2d57600080fd5b505190508415613d7b5782811015613d765760405162461bcd60e51b8152600401808060200182810382526030815260200180615a956030913960400191505060405180910390fd5b613dba565b82811115613dba5760405162461bcd60e51b8152600401808060200182810382526031815260200180615b936031913960400191505060405180910390fd5b7f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b0316630af785596040518163ffffffff1660e01b815260040160206040518083038186803b158015613e1357600080fd5b505afa158015613e27573d6000803e3d6000fd5b505050506040513d6020811015613e3d57600080fd5b505160408051633cc8e33b60e21b81526001600160a01b038d811660048301528c811660248301528b811660448301528815156064830152608482018a905260a48201859052600060c48301819052925193169263f3238cec9260e48084019391929182900301818387803b158015613eb557600080fd5b505af1158015613ec9573d6000803e3d6000fd5b5050505060007f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b031663b0f479a16040518163ffffffff1660e01b815260040160206040518083038186803b158015613f2857600080fd5b505afa158015613f3c573d6000803e3d6000fd5b505050506040513d6020811015613f5257600080fd5b505160408051632662166b60e01b81526001600160a01b038e811660048301528d811660248301528c81166044830152606482018c9052608482018b905289151560a483015288811660c483015291519190921691632662166b9160e48083019260209291908290030181600087803b158015613fce57600080fd5b505af1158015613fe2573d6000803e3d6000fd5b505050506040513d6020811015613ff857600080fd5b50519b9a5050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261405b908490615166565b505050565b60008351600214156140a7576140a08460008151811061407c57fe5b60200260200101518560018151811061409157fe5b60200260200101518585615217565b9050613c23565b60405162461bcd60e51b8152600401808060200182810382526029815260200180615c296029913960400191505060405180910390fd5b60007f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a279050806001600160a01b0316632e1a7d4d846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561414957600080fd5b505af115801561415d573d6000803e3d6000fd5b5050600254604051600093506001600160a01b0386169250869084818181858888f193505050503d80600081146141b0576040519150601f19603f3d011682016040523d82523d6000602084013e6141b5565b606091505b5050905080156141c6575050612e48565b816001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561420157600080fd5b505af1158015614215573d6000803e3d6000fd5b5050505050816001600160a01b031663a9059cbb84866040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561427157600080fd5b505af1158015614285573d6000803e3d6000fd5b505050506040513d602081101561429b57600080fd5b505050505050565b6000828211156142fa576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b341561437b577f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a276001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561436157600080fd5b505af1158015614375573d6000803e3d6000fd5b50505050505b565b6001600160a01b038a166000908152601160205260408120546143a190600161510c565b6001600160a01b03808d1660008181526011602090815260408083208690558051610180810182529384529083018f9052928d1692820192909252606081018b9052608081018a905260a0810189905287151560c082015260e081018790526101008101869052436101208201524261014082015284151561016082015291925061442c8d84612a14565b6000818152601260209081526040909120845181546001600160a01b0319166001600160a01b03909116178155848201518051939450859391926144789260018501929091019061587f565b5060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a81548160ff02191690831515021790555060e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b0160006101000a81548160ff021916908315150217905550905050600c8190806001815401808255809150506001900390600052602060002001600090919091909150558c6001600160a01b03167fa89f00a1c1cd0de066abac1a05f9314520fef2a9b98f6a99ff4548ed1161c03c8d8d8d8d8d8d8d8d8c43423a60405180806020018d6001600160a01b031681526020018c81526020018b81526020018a8152602001891515815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528e818151815260200191508051906020019060200280838360005b83811015614620578181015183820152602001614608565b505050509050019d505050505050505050505050505060405180910390a250505050505050505050505050565b3360009081526010602052604081205460ff1615614684574361467b600a548661510c90919063ffffffff16565b11159050613c23565b336001600160a01b0383161480156146b05750426146ad6003548561510c90919063ffffffff16565b11155b614701576040805162461bcd60e51b815260206004820152601960248201527f506f736974696f6e526f757465723a20666f7262696464656e00000000000000604482015290519081900360640190fd5b5060019392505050565b3390565b600080614720888888888888615371565b905080156147df57600061475761271061475161474a6004546127106142a390919063ffffffff16565b8a906155cf565b90615628565b9050600061476588836142a3565b905060008960018b51038151811061477957fe5b602002602001015190506147bb8260066000846001600160a01b03166001600160a01b031681526020019081526020016000205461510c90919063ffffffff16565b6001600160a01b039091166000908152600660205260409020555091506147e49050565b859150505b9695505050505050565b60007f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561484957600080fd5b505afa15801561485d573d6000803e3d6000fd5b505050506040513d602081101561487357600080fd5b505160408051631f94a27560e31b815290519192506000916001600160a01b037f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c169163fca513a8916004808301926020929190829003018186803b1580156148db57600080fd5b505afa1580156148ef573d6000803e3d6000fd5b505050506040513d602081101561490557600080fd5b5051604080516303b6b4bb60e51b81526001600160a01b0389811660048301528715156024830152915191909216916376d69760916044808301926020929190829003018186803b15801561495957600080fd5b505afa15801561496d573d6000803e3d6000fd5b505050506040513d602081101561498357600080fd5b5051905083156149d157828111156149cc5760405162461bcd60e51b8152600401808060200182810382526031815260200180615b936031913960400191505060405180910390fd5b614a10565b82811015614a105760405162461bcd60e51b8152600401808060200182810382526030815260200180615a956030913960400191505060405180910390fd5b8315614b01576001600160a01b0386166000908152600760205260409020548015801590614abf575080614abd87856001600160a01b031663f07456ce8b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015614a8b57600080fd5b505afa158015614a9f573d6000803e3d6000fd5b505050506040513d6020811015614ab557600080fd5b50519061510c565b115b15614afb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806158fa602e913960400191505060405180910390fd5b50614bb6565b6001600160a01b0386166000908152600860205260409020548015801590614b78575080614b7687856001600160a01b0316638a78daa88b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015614a8b57600080fd5b115b15614bb45760405162461bcd60e51b815260040180806020018281038252602f815260200180615af0602f913960400191505060405180910390fd5b505b7f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b0316630af785596040518163ffffffff1660e01b815260040160206040518083038186803b158015614c0f57600080fd5b505afa158015614c23573d6000803e3d6000fd5b505050506040513d6020811015614c3957600080fd5b505160408051633cc8e33b60e21b81526001600160a01b038b811660048301528a81166024830152898116604483015287151560648301526084820189905260a48201859052600160c48301529151919092169163f3238cec9160e480830192600092919082900301818387803b158015614cb357600080fd5b505af1158015614cc7573d6000803e3d6000fd5b505050507f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b031663b0f479a16040518163ffffffff1660e01b815260040160206040518083038186803b158015614d2457600080fd5b505afa158015614d38573d6000803e3d6000fd5b505050506040513d6020811015614d4e57600080fd5b505160408051630f8ee8bb60e11b81526001600160a01b038b811660048301528a81166024830152898116604483015260648201899052871515608483015291519190921691631f1dd1769160a480830192600092919082900301818387803b158015614dba57600080fd5b505af1158015614dce573d6000803e3d6000fd5b505050505050505050505050565b6001600160a01b038b16600090815260136020526040812054614e0090600161510c565b905080601360008e6001600160a01b03166001600160a01b03168152602001908152602001600020819055506000604051806101a001604052808e6001600160a01b031681526020018d81526020018c6001600160a01b031681526020018b81526020018a81526020018915158152602001886001600160a01b0316815260200187815260200186815260200185815260200143815260200142815260200184151581525090506000614eb38e84612a14565b6000818152601460209081526040909120845181546001600160a01b0319166001600160a01b0390911617815584820151805193945085939192614eff9260018501929091019061587f565b5060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff02191690831515021790555060c08201518160050160016101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e0820151816006015561010082015181600701556101208201518160080155610140820151816009015561016082015181600a015561018082015181600b0160006101000a81548160ff021916908315150217905550905050600d8190806001815401808255809150506001900390600052602060002001600090919091909150558d6001600160a01b03167f506f2634e4508d88b04b7511af75c6d4c29b2b6f4f5067676b9400b28f3761d28e8e8e8e8e8e8e8e8e8d434260405180806020018d6001600160a01b031681526020018c81526020018b81526020018a15158152602001896001600160a01b0316815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528e818151815260200191508051906020019060200280838360005b838110156150de5781810151838201526020016150c6565b505050509050019d505050505050505050505050505060405180910390a25050505050505050505050505050565b600082820183811015613c23576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006151bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661568f9092919063ffffffff16565b80519091501561405b578080602001905160208110156151da57600080fd5b505161405b5760405162461bcd60e51b815260040180806020018281038252602a815260200180615cb1602a913960400191505060405180910390fd5b6000807f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561527357600080fd5b505afa158015615287573d6000803e3d6000fd5b505050506040513d602081101561529d57600080fd5b505160408051634998b10960e11b81526001600160a01b038981166004830152888116602483015286811660448301529151919092169163933162129160648083019260209291908290030181600087803b1580156152fb57600080fd5b505af115801561530f573d6000803e3d6000fd5b505050506040513d602081101561532557600080fd5b50519050838110156153685760405162461bcd60e51b815260040180806020018281038252602b8152602001806159db602b913960400191505060405180910390fd5b95945050505050565b600082615380575060006147e4565b8161538d575060016147e4565b60008660018851038151811061539f57fe5b6020026020010151905060007f000000000000000000000000b29ea150c870ea830d9890d94f326cb1b273ce8c6001600160a01b0316638d928af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561540457600080fd5b505afa158015615418573d6000803e3d6000fd5b505050506040513d602081101561542e57600080fd5b505160408051634a3f088d60e01b81526001600160a01b038c8116600483015285811660248301528981166044830152881515606483015291519293506000928392851691634a3f088d91608480830192610100929190829003018186803b15801561549957600080fd5b505afa1580156154ad573d6000803e3d6000fd5b505050506040513d6101008110156154c457600080fd5b5080516020909101519092509050816154e45760009450505050506147e4565b60006154f0838861510c565b90506000846001600160a01b0316630a48d5a9878d6040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561554957600080fd5b505afa15801561555d573d6000803e3d6000fd5b505050506040513d602081101561557357600080fd5b505190506000615583848361510c565b9050600061559785614751886127106155cf565b905060006155b88361475160055461271001886155cf90919063ffffffff16565b919091109f9e505050505050505050505050505050565b6000826155de57506000612a54565b828202828482816155eb57fe5b0414613c235760405162461bcd60e51b8152600401808060200182810382526021815260200180615b526021913960400191505060405180910390fd5b600080821161567e576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161568757fe5b049392505050565b6060613c208484600085856156a3856157b4565b6156f4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b602083106157325780518252601f199092019160209182019101615713565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114615794576040519150601f19603f3d011682016040523d82523d6000602084013e615799565b606091505b50915091506157a98282866157ba565b979650505050505050565b3b151590565b606083156157c9575081613c23565b8251156157d95782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561582357818101518382015260200161580b565b50505050905090810190601f1680156158505780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b508054600082559060005260206000209081019061587c91906158e4565b50565b8280548282559060005260206000209081019282156158d4579160200282015b828111156158d457825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061589f565b506158e09291506158e4565b5090565b5b808211156158e057600081556001016158e556fe42617365506f736974696f6e4d616e616765723a206d617820676c6f62616c206c6f6e6773206578636565646564506f736974696f6e526f757465723a20696e76616c696420657865637574696f6e4665655265656e7472616e637947756172643a207265656e7472616e742063616c6c00506f736974696f6e526f757465723a20696e76616c6964206d73672e76616c75654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373506f736974696f6e526f757465723a206d617854696d6544656c617920697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e73756666696369656e7420616d6f756e744f7574506f736974696f6e526f757465723a20696e637265617365506f736974696f6e526571756573744b657973537461727420697320746f6f2068696768506f736974696f6e526f757465723a206d696e426c6f636b44656c61794b656570657220697320746f6f2068696768506f736974696f6e526f757465723a20696e76616c6964205f70617468206c656e67746842617365506f736974696f6e4d616e616765723a206d61726b207072696365206c6f776572207468616e206c696d697442617365506f736974696f6e4d616e616765723a206465706f73697446656520697320746f6f206869676842617365506f736974696f6e4d616e616765723a206d617820676c6f62616c2073686f72747320657863656564656442617365506f736974696f6e4d616e616765723a206d696e54696d6544656c61795075626c696320697320746f6f2068696768536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657242617365506f736974696f6e4d616e616765723a206d61726b20707269636520686967686572207468616e206c696d6974506f736974696f6e526f757465723a206d696e457865637574696f6e46656520697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e637265617365506f736974696f6e42756666657242707320697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e76616c6964205f706174682e6c656e677468506f736974696f6e526f757465723a206465637265617365506f736974696f6e526571756573744b657973537461727420697320746f6f206869676842617365506f736974696f6e4d616e616765723a20696e76616c69642073656e6465725361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564506f736974696f6e526f757465723a2063616c6c6572206973206e6f742074686520706f736974696f6e206b6565706572506f736974696f6e526f757465723a207265717565737420686173206578706972656442617365506f736974696f6e4d616e616765723a204f6e6c792050686c704d616e616765722063616e20776974686472617720666565a26469706673582212207461fa329d0fcdc8200d8c5a8143ee7e08bbd41bd405e9acea33174ad69f5ca764736f6c63430007060033