Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
GmxV2Adapter
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "../../components/ImplementationGuard.sol";
import "./interfaces/gmx/IOrderCallbackReceiver.sol";
import "./interfaces/gmx/IRoleStore.sol";
import "./libraries/LibGmxV2.sol";
import "./libraries/LibDebt.sol";
import "./libraries/LibConfig.sol";
import "./Storage.sol";
import "./Getter.sol";
contract GmxV2Adapter is
Storage,
Getter,
Initializable,
ReentrancyGuardUpgradeable,
ImplementationGuard,
IOrderCallbackReceiver
{
using LibUtils for uint256;
using MathUpgradeable for uint256;
using LibGmxV2 for GmxAdapterStoreV2;
using LibConfig for GmxAdapterStoreV2;
using LibDebt for GmxAdapterStoreV2;
using LibUtils for GmxAdapterStoreV2;
receive() external payable {}
modifier onlyTrader() {
require(_isValidCaller(), "OnlyTraderOrFactory");
_;
}
modifier onlyKeeper() {
require(IProxyFactory(_store.factory).isKeeper(msg.sender), "onlyKeeper");
_;
}
modifier onlyValidCallbackSender() {
require(_isValidCallbackSender(), "InvalidCallbackSender");
_;
}
modifier onlyNotLiquidating() {
require(!_store.account.isLiquidating, "Liquidating");
_;
}
function initialize(
uint256 projectId_,
address liquidityPool,
address owner,
address collateralToken,
address market,
bool isLong
) external initializer onlyDelegateCall {
require(liquidityPool != address(0), "InvalidLiquidityPool");
require(projectId_ == PROJECT_ID, "InvalidProject");
_store.factory = msg.sender;
_store.liquidityPool = liquidityPool;
_store.positionKey = keccak256(abi.encode(address(this), market, collateralToken, isLong));
_store.account.isLong = isLong;
_store.account.market = market;
_store.account.owner = owner;
_store.updateConfigs();
_store.setupTokens(collateralToken);
_store.setupCallback();
}
/// @notice Place a openning request on GMXv2.
function placeOrder(
OrderCreateParams memory createParams
) external payable onlyTrader onlyNotLiquidating nonReentrant returns (bytes32) {
_store.updateConfigs();
if (_isIncreasing(createParams.orderType)) {
return _store.openPosition(createParams);
} else {
return _store.closePosition(createParams);
}
}
function updateOrder(
bytes32 key,
uint256 sizeDeltaUsd,
uint256 acceptablePrice,
uint256 triggerPrice
) external onlyTrader onlyNotLiquidating nonReentrant {
_store.updateConfigs();
_store.updateOrder(key, sizeDeltaUsd, acceptablePrice, triggerPrice);
}
function liquidatePosition(
Prices memory prices,
uint256 executionFee,
uint256 callbackGasLimit
) external payable onlyKeeper onlyNotLiquidating nonReentrant {
_store.updateConfigs();
_store.liquidatePosition(prices, executionFee, callbackGasLimit);
}
function cancelOrder(bytes32 key) external onlyTrader onlyNotLiquidating nonReentrant {
_store.updateConfigs();
_store.cancelOrder(key);
}
function cancelExpiredOrder(bytes32 key) external onlyNotLiquidating nonReentrant {
_store.updateConfigs();
_store.cancelExpiredOrder(key);
}
// =========================================== fee && reward ===========================================
function claimFundingFees(
address[] memory markets,
address[] memory tokens
) external payable returns (uint256[] memory) {
return
IExchangeRouter(_store.projectConfigs.exchangeRouter).claimFundingFees(
markets,
tokens,
_store.account.owner
);
}
function claimToken(address token) external returns (uint256) {
return _store.claimToken(token);
}
function claimNativeToken() external returns (uint256) {
return _store.claimNativeToken();
}
// =========================================== calbacks ===========================================
function afterOrderExecution(
bytes32 key,
IOrder.Props memory,
IEvent.EventLogData memory
) external onlyValidCallbackSender {
uint256 oldDebtCollateralAmount = _store.account.debtCollateralAmount;
uint256 oldInflightDebtCollateralAmount = _store.account.inflightDebtCollateralAmount;
uint256 oldPendingFeeCollateralAmount = _store.account.pendingFeeCollateralAmount;
uint256 oldDebtEntryFunding = _store.account.debtEntryFunding;
require(!_store.isOrderExist(key), "OrderNotFilled");
OrderRecord memory pendingOrder = _store.removeOrder(key);
if (!pendingOrder.isIncreasing) {
if (_store.account.debtCollateralAmount > 0) {
Prices memory prices = _store.getOraclePrices();
_store.repayDebt(prices);
} else {
_store.refundTokens();
}
}
_store.claimNativeToken();
IEventEmitter(_store.projectConfigs.eventEmitter).onUpdateDebt(
_store.account.owner,
key,
oldDebtCollateralAmount,
oldInflightDebtCollateralAmount,
oldPendingFeeCollateralAmount,
oldDebtEntryFunding,
_store.account.debtCollateralAmount,
_store.account.inflightDebtCollateralAmount,
_store.account.pendingFeeCollateralAmount,
_store.account.debtEntryFunding
);
}
function afterOrderCancellation(
bytes32 key,
IOrder.Props memory,
IEvent.EventLogData memory
) external onlyValidCallbackSender {
uint256 oldDebtCollateralAmount = _store.account.debtCollateralAmount;
uint256 oldInflightDebtCollateralAmount = _store.account.inflightDebtCollateralAmount;
uint256 oldPendingFeeCollateralAmount = _store.account.pendingFeeCollateralAmount;
uint256 oldDebtEntryFunding = _store.account.debtEntryFunding;
require(!_store.isOrderExist(key), "OrderNotCancelled");
OrderRecord memory pendingOrder = _store.removeOrder(key);
if (pendingOrder.isIncreasing) {
_store.repayCancelledDebt(pendingOrder.collateralAmount, pendingOrder.debtCollateralAmount);
}
_store.claimNativeToken();
IEventEmitter(_store.projectConfigs.eventEmitter).onUpdateDebt(
_store.account.owner,
key,
oldDebtCollateralAmount,
oldInflightDebtCollateralAmount,
oldPendingFeeCollateralAmount,
oldDebtEntryFunding,
_store.account.debtCollateralAmount,
_store.account.inflightDebtCollateralAmount,
_store.account.pendingFeeCollateralAmount,
_store.account.debtEntryFunding
);
}
function afterOrderFrozen(
bytes32 key,
IOrder.Props memory,
IEvent.EventLogData memory
) external onlyValidCallbackSender {}
// =========================================== internals ===========================================
function _isValidCallbackSender() internal view returns (bool) {
if (IProxyFactory(_store.factory).isKeeper(msg.sender)) {
return true;
}
// let it pass if the caller is a gmx controller
IRoleStore roleStore = IRoleStore(IDataStore(_store.projectConfigs.dataStore).roleStore());
if (roleStore.hasRole(msg.sender, CONTROLLER)) {
return true;
}
return false;
}
function _isValidCaller() internal view returns (bool) {
if (msg.sender == _store.factory) {
return true;
}
if (msg.sender == _store.account.owner) {
return true;
}
return false;
}
function _isIncreasing(IOrder.OrderType orderType) internal pure returns (bool) {
return orderType == IOrder.OrderType.MarketIncrease || orderType == IOrder.OrderType.LimitIncrease;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControlUpgradeable {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Internal function that returns the initialized version. Returns `_initialized`
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Internal function that returns the initialized version. Returns `_initializing`
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 ReentrancyGuardUpgradeable is Initializable {
// 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;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20PermitUpgradeable {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
import "../extensions/draft-IERC20PermitUpgradeable.sol";
import "../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable {
using AddressUpgradeable for address;
function safeTransfer(
IERC20Upgradeable token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20Upgradeable 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(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20PermitUpgradeable token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableMap.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
pragma solidity ^0.8.0;
import "./EnumerableSetUpgradeable.sol";
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* The following map types are supported:
*
* - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
* - `address -> uint256` (`AddressToUintMap`) since v4.6.0
* - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0
* - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
* - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableMap.
* ====
*/
library EnumerableMapUpgradeable {
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set;
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct Bytes32ToBytes32Map {
// Storage of keys
EnumerableSetUpgradeable.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
Bytes32ToBytes32Map storage map,
bytes32 key,
bytes32 value
) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
// UintToUintMap
struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
UintToUintMap storage map,
uint256 key,
uint256 value
) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToUintMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}
// UintToAddressMap
struct UintToAddressMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
UintToAddressMap storage map,
uint256 key,
address value
) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToAddressMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
}
// AddressToUintMap
struct AddressToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
AddressToUintMap storage map,
address key,
uint256 value
) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(AddressToUintMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(AddressToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
AddressToUintMap storage map,
address key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
}
// Bytes32ToUintMap
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
Bytes32ToUintMap storage map,
bytes32 key,
uint256 value
) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (key, uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, key);
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToUintMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, key, errorMessage));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSetUpgradeable {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
import "../../interfaces/IPriceHub.sol";
import "./libraries/LibGmxV2.sol";
import "./libraries/LibUtils.sol";
import "./Storage.sol";
abstract contract Getter is Storage {
using LibUtils for IGmxV2Adatper.GmxAdapterStoreV2;
using LibGmxV2 for IGmxV2Adatper.GmxAdapterStoreV2;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set;
function positionKey() external view returns (bytes32) {
return _store.positionKey;
}
function muxAccountState() external view returns (AccountState memory) {
return _store.account;
}
function getPendingOrders() external view returns (PendingOrder[] memory pendingOrders) {
uint256 count = _store.pendingOrderIndexes.length();
if (count == 0) {
return pendingOrders;
}
pendingOrders = new PendingOrder[](count);
for (uint256 i = 0; i < count; i++) {
bytes32 key = _store.pendingOrderIndexes.at(i);
OrderRecord memory record = _store.pendingOrders[key];
pendingOrders[i] = PendingOrder({
key: key,
debtCollateralAmount: record.debtCollateralAmount,
timestamp: record.timestamp,
blockNumber: record.blockNumber,
isIncreasing: record.isIncreasing
});
}
}
// 1e18
function getMarginRate(Prices memory prices) external view returns (uint256) {
return _store.getMarginRate(prices); // 1e18
}
function isLiquidateable(Prices memory prices) external view returns (bool) {
uint256 sizeInUsd = IReaderLite(_store.projectConfigs.reader).getPositionSizeInUsd(
_store.projectConfigs.dataStore,
_store.positionKey
);
if (sizeInUsd == 0) {
return false;
}
return _store.getMarginRate(prices) < uint256(_store.marketConfigs.maintenanceMarginRate) * 1e13;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
bytes32 constant MIN_COLLATERAL_USD = keccak256(abi.encode("MIN_COLLATERAL_USD"));
bytes32 constant POSITION_LIST = keccak256(abi.encode("POSITION_LIST"));
interface IDataStore {
function roleStore() external view returns (address);
function getUint(bytes32 key) external view returns (uint256);
function getInt(bytes32 key) external view returns (int256);
function getAddress(bytes32 key) external view returns (address);
function getBool(bytes32 key) external view returns (bool);
function getString(bytes32 key) external view returns (string memory);
function getBytes32(bytes32 key) external view returns (bytes32);
function getUintArray(bytes32 key) external view returns (uint256[] memory);
function getIntArray(bytes32 key) external view returns (int256[] memory);
function getAddressArray(bytes32 key) external view returns (address[] memory);
function getBoolArray(bytes32 key) external view returns (bool[] memory);
function getStringArray(bytes32 key) external view returns (string[] memory);
function getBytes32Array(bytes32 key) external view returns (bytes32[] memory);
function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool);
function getBytes32Count(bytes32 setKey) external view returns (uint256);
function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory);
function containsAddress(bytes32 setKey, address value) external view returns (bool);
function getAddressCount(bytes32 setKey) external view returns (uint256);
function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory);
function containsUint(bytes32 setKey, uint256 value) external view returns (bool);
function getUintCount(bytes32 setKey) external view returns (uint256);
function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IEvent {
struct EmitPositionDecreaseParams {
bytes32 key;
address account;
address market;
address collateralToken;
bool isLong;
}
struct EventLogData {
AddressItems addressItems;
UintItems uintItems;
IntItems intItems;
BoolItems boolItems;
Bytes32Items bytes32Items;
BytesItems bytesItems;
StringItems stringItems;
}
struct AddressItems {
AddressKeyValue[] items;
AddressArrayKeyValue[] arrayItems;
}
struct UintItems {
UintKeyValue[] items;
UintArrayKeyValue[] arrayItems;
}
struct IntItems {
IntKeyValue[] items;
IntArrayKeyValue[] arrayItems;
}
struct BoolItems {
BoolKeyValue[] items;
BoolArrayKeyValue[] arrayItems;
}
struct Bytes32Items {
Bytes32KeyValue[] items;
Bytes32ArrayKeyValue[] arrayItems;
}
struct BytesItems {
BytesKeyValue[] items;
BytesArrayKeyValue[] arrayItems;
}
struct StringItems {
StringKeyValue[] items;
StringArrayKeyValue[] arrayItems;
}
struct AddressKeyValue {
string key;
address value;
}
struct AddressArrayKeyValue {
string key;
address[] value;
}
struct UintKeyValue {
string key;
uint256 value;
}
struct UintArrayKeyValue {
string key;
uint256[] value;
}
struct IntKeyValue {
string key;
int256 value;
}
struct IntArrayKeyValue {
string key;
int256[] value;
}
struct BoolKeyValue {
string key;
bool value;
}
struct BoolArrayKeyValue {
string key;
bool[] value;
}
struct Bytes32KeyValue {
string key;
bytes32 value;
}
struct Bytes32ArrayKeyValue {
string key;
bytes32[] value;
}
struct BytesKeyValue {
string key;
bytes value;
}
struct BytesArrayKeyValue {
string key;
bytes[] value;
}
struct StringKeyValue {
string key;
string value;
}
struct StringArrayKeyValue {
string key;
string[] value;
}
event EventLog(address msgSender, string eventName, string indexed eventNameHash, IEvent.EventLogData eventData);
event EventLog1(
address msgSender,
string eventName,
string indexed eventNameHash,
bytes32 indexed topic1,
IEvent.EventLogData eventData
);
event EventLog2(
address msgSender,
string eventName,
string indexed eventNameHash,
bytes32 indexed topic1,
bytes32 indexed topic2,
IEvent.EventLogData eventData
);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IOrder.sol";
interface IExchangeRouter {
struct CreateOrderParams {
CreateOrderParamsAddresses addresses;
CreateOrderParamsNumbers numbers;
IOrder.OrderType orderType;
IOrder.DecreasePositionSwapType decreasePositionSwapType;
bool isLong;
bool shouldUnwrapNativeToken;
bytes32 referralCode;
}
// @param receiver for order.receiver
// @param callbackContract for order.callbackContract
// @param market for order.market
// @param initialCollateralToken for order.initialCollateralToken
// @param swapPath for order.swapPath
struct CreateOrderParamsAddresses {
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address initialCollateralToken;
address[] swapPath;
}
// @param sizeDeltaUsd for order.sizeDeltaUsd
// @param triggerPrice for order.triggerPrice
// @param acceptablePrice for order.acceptablePrice
// @param executionFee for order.executionFee
// @param callbackGasLimit for order.callbackGasLimit
// @param minOutputAmount for order.minOutputAmount
struct CreateOrderParamsNumbers {
uint256 sizeDeltaUsd;
uint256 initialCollateralDeltaAmount;
uint256 triggerPrice;
uint256 acceptablePrice;
uint256 executionFee;
uint256 callbackGasLimit;
uint256 minOutputAmount;
}
function sendWnt(address receiver, uint256 amount) external payable;
function sendTokens(address token, address receiver, uint256 amount) external payable;
function sendNativeToken(address receiver, uint256 amount) external payable;
function depositHandler() external view returns (address);
function withdrawalHandler() external view returns (address);
function orderHandler() external view returns (address);
/**
* @dev Creates a new order with the given amount, order parameters. The order is
* created by transferring the specified amount of collateral tokens from the caller's account to the
* order store, and then calling the `createOrder()` function on the order handler contract. The
* referral code is also set on the caller's account using the referral storage contract.
*/
function createOrder(CreateOrderParams calldata params) external payable returns (bytes32);
function setSavedCallbackContract(address market, address callbackContract) external payable;
/**
* @dev Updates the given order with the specified size delta, acceptable price, and trigger price.
* The `updateOrder()` feature must be enabled for the given order type. The caller must be the owner
* of the order, and the order must not be a market order. The size delta, trigger price, and
* acceptable price are updated on the order, and the order is unfrozen. Any additional WNT that is
* transferred to the contract is added to the order's execution fee. The updated order is then saved
* in the order store, and an `OrderUpdated` event is emitted.
*
* @param key The unique ID of the order to be updated
* @param sizeDeltaUsd The new size delta for the order
* @param acceptablePrice The new acceptable price for the order
* @param triggerPrice The new trigger price for the order
*/
function updateOrder(
bytes32 key,
uint256 sizeDeltaUsd,
uint256 acceptablePrice,
uint256 triggerPrice,
uint256 minOutputAmount
) external payable;
/**
* @dev Cancels the given order. The `cancelOrder()` feature must be enabled for the given order
* type. The caller must be the owner of the order, and the order must not be a market order. The
* order is cancelled by calling the `cancelOrder()` function in the `OrderUtils` contract. This
* function also records the starting gas amount and the reason for cancellation, which is passed to
* the `cancelOrder()` function.
*
* @param key The unique ID of the order to be cancelled
*/
function cancelOrder(bytes32 key) external payable;
/**
* @dev Claims funding fees for the given markets and tokens on behalf of the caller, and sends the
* fees to the specified receiver. The length of the `markets` and `tokens` arrays must be the same.
* For each market-token pair, the `claimFundingFees()` function in the `MarketUtils` contract is
* called to claim the fees for the caller.
*
* @param markets An array of market addresses
* @param tokens An array of token addresses, corresponding to the given markets
* @param receiver The address to which the claimed fees should be sent
*/
function claimFundingFees(
address[] memory markets,
address[] memory tokens,
address receiver
) external payable returns (uint256[] memory);
function claimCollateral(
address[] memory markets,
address[] memory tokens,
uint256[] memory timeKeys,
address receiver
) external payable returns (uint256[] memory);
/**
* @dev Claims affiliate rewards for the given markets and tokens on behalf of the caller, and sends
* the rewards to the specified receiver. The length of the `markets` and `tokens` arrays must be
* the same. For each market-token pair, the `claimAffiliateReward()` function in the `ReferralUtils`
* contract is called to claim the rewards for the caller.
*
* @param markets An array of market addresses
* @param tokens An array of token addresses, corresponding to the given markets
* @param receiver The address to which the claimed rewards should be sent
*/
function claimAffiliateRewards(
address[] memory markets,
address[] memory tokens,
address receiver
) external payable returns (uint256[] memory);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IPrice.sol";
interface IMarket {
struct Props {
address marketToken;
address indexToken;
address longToken;
address shortToken;
}
struct MarketPrices {
IPrice.Props indexTokenPrice;
IPrice.Props longTokenPrice;
IPrice.Props shortTokenPrice;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IExchangeRouter.sol";
interface IOrder {
enum OrderType {
// @dev MarketSwap: swap token A to token B at the current market price
// the order will be cancelled if the minOutputAmount cannot be fulfilled
MarketSwap,
// @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled
LimitSwap,
// @dev MarketIncrease: increase position at the current market price
// the order will be cancelled if the position cannot be increased at the acceptablePrice
MarketIncrease,
// @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled
LimitIncrease,
// @dev MarketDecrease: decrease position at the current market price
// the order will be cancelled if the position cannot be decreased at the acceptablePrice
MarketDecrease,
// @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
LimitDecrease,
// @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
StopLossDecrease,
// @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met
Liquidation
}
enum DecreasePositionSwapType {
NoSwap,
SwapPnlTokenToCollateralToken,
SwapCollateralTokenToPnlToken
}
struct Addresses {
address account;
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address initialCollateralToken;
address[] swapPath;
}
struct Numbers {
OrderType orderType;
DecreasePositionSwapType decreasePositionSwapType;
uint256 sizeDeltaUsd;
uint256 initialCollateralDeltaAmount;
uint256 triggerPrice;
uint256 acceptablePrice;
uint256 executionFee;
uint256 callbackGasLimit;
uint256 minOutputAmount;
uint256 updatedAtBlock;
}
struct Flags {
bool isLong;
bool shouldUnwrapNativeToken;
bool isFrozen;
}
struct Props {
Addresses addresses;
Numbers numbers;
Flags flags;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IEvent.sol";
import "./IOrder.sol";
// @title IOrderCallbackReceiver
// @dev interface for an order callback contract
interface IOrderCallbackReceiver {
// @dev called after an order execution
// @param key the key of the order
// @param order the order that was executed
function afterOrderExecution(bytes32 key, IOrder.Props memory order, IEvent.EventLogData memory eventData) external;
// @dev called after an order cancellation
// @param key the key of the order
// @param order the order that was cancelled
function afterOrderCancellation(
bytes32 key,
IOrder.Props memory order,
IEvent.EventLogData memory eventData
) external;
// @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info
// @param key the key of the order
// @param order the order that was frozen
function afterOrderFrozen(bytes32 key, IOrder.Props memory order, IEvent.EventLogData memory eventData) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IPosition {
struct Props {
Addresses addresses;
Numbers numbers;
Flags flags;
}
struct Addresses {
address account;
address market;
address collateralToken;
}
struct Numbers {
uint256 sizeInUsd;
uint256 sizeInTokens;
uint256 collateralAmount;
uint256 borrowingFactor;
uint256 fundingFeeAmountPerSize;
uint256 longTokenClaimableFundingAmountPerSize;
uint256 shortTokenClaimableFundingAmountPerSize;
uint256 increasedAtBlock;
uint256 decreasedAtBlock;
}
struct Flags {
bool isLong;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IPrice.sol";
interface IPositionPricing {
struct PositionBorrowingFees {
uint256 borrowingFeeUsd;
uint256 borrowingFeeAmount;
uint256 borrowingFeeReceiverFactor;
uint256 borrowingFeeAmountForFeeReceiver;
}
struct PositionFundingFees {
uint256 fundingFeeAmount;
uint256 claimableLongTokenAmount;
uint256 claimableShortTokenAmount;
uint256 latestFundingFeeAmountPerSize;
uint256 latestLongTokenClaimableFundingAmountPerSize;
uint256 latestShortTokenClaimableFundingAmountPerSize;
}
struct PositionReferralFees {
bytes32 referralCode;
address affiliate;
address trader;
uint256 totalRebateFactor;
uint256 traderDiscountFactor;
uint256 totalRebateAmount;
uint256 traderDiscountAmount;
uint256 affiliateRewardAmount;
}
struct PositionUiFees {
address uiFeeReceiver;
uint256 uiFeeReceiverFactor;
uint256 uiFeeAmount;
}
struct PositionFees {
PositionReferralFees referral;
PositionFundingFees funding;
PositionBorrowingFees borrowing;
PositionUiFees ui;
IPrice.Props collateralTokenPrice;
uint256 positionFeeFactor;
uint256 protocolFeeAmount;
uint256 positionFeeReceiverFactor;
uint256 feeReceiverAmount;
uint256 feeAmountForPool;
uint256 positionFeeAmountForPool;
uint256 positionFeeAmount;
uint256 totalCostAmountExcludingFunding;
uint256 totalCostAmount;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IPrice {
struct Props {
uint256 min;
uint256 max;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IPrice.sol";
import "./IOrder.sol";
import "./IMarket.sol";
import "./IPosition.sol";
import "./IPositionPricing.sol";
interface IReader {
struct ExecutionPriceResult {
int256 priceImpactUsd;
uint256 priceImpactDiffUsd;
uint256 executionPrice;
}
struct PositionInfo {
IPosition.Props position;
IPositionPricing.PositionFees fees;
ExecutionPriceResult executionPriceResult;
int256 basePnlUsd;
int256 uncappedBasePnlUsd;
int256 pnlAfterPriceImpactUsd;
}
function getPositionInfo(
address dataStore,
address referralStorage,
bytes32 positionKey,
IMarket.MarketPrices memory prices,
uint256 sizeDeltaUsd,
address uiFeeReceiver,
bool usePositionSizeAsSizeDeltaUsd
) external view returns (PositionInfo memory);
function getPosition(address dataStore, bytes32 key) external view returns (IPosition.Props memory);
function getOrder(address dataStore, bytes32 key) external view returns (IOrder.Props memory);
function getAccountOrders(
address dataStore,
address account,
uint256 start,
uint256 end
) external view returns (IOrder.Props[] memory);
function getMarket(address dataStore, address key) external view returns (IMarket.Props memory);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IMarket.sol";
interface IReaderLite {
function getMarketTokens(
address dataStore,
address key
) external view returns (address marketToken, address indexToken, address longToken, address shortToken);
function isOrderExist(address dataStore, bytes32 orderKey) external view returns (bool);
function getPositionSizeInUsd(address dataStore, bytes32 positionKey) external view returns (uint256);
function getPositionMarginInfo(
address dataStore,
address referralStorage,
bytes32 positionKey,
IMarket.MarketPrices memory prices
)
external
view
returns (uint256 collateralAmount, uint256 sizeInUsd, uint256 totalCostAmount, int256 pnlAfterPriceImpactUsd);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
bytes32 constant CONTROLLER = keccak256(abi.encode("CONTROLLER"));
interface IRoleStore {
function hasRole(address account, bytes32 roleKey) external view returns (bool);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "../interfaces/IGmxV2Adatper.sol";
interface IEventEmitter {
event PlacePositionOrder(
address indexed proxy,
address indexed proxyOwner,
IGmxV2Adatper.OrderCreateParams createParams,
IGmxV2Adatper.PositionResult result
);
event PlaceLiquidateOrder(address indexed proxy, address indexed proxyOwner, IGmxV2Adatper.PositionResult result);
event BorrowCollateral(address indexed proxy, address indexed proxyOwner, IGmxV2Adatper.DebtResult result);
event RepayCollateral(address indexed proxy, address indexed proxyOwner, IGmxV2Adatper.DebtResult result);
event UpdateOrder(
address indexed proxy,
address indexed proxyOwner,
bytes32 indexed key,
uint256 sizeDeltaUsd,
uint256 acceptablePrice,
uint256 triggerPrice
);
event CancelOrder(address indexed proxy, address indexed proxyOwner, bytes32 key);
event UpdateDebt(
address indexed proxy,
address indexed proxyOwner,
bytes32 indexed key,
uint256 oldDebtCollateralAmount,
uint256 oldInflightDebtCollateralAmount,
uint256 oldPendingFeeCollateralAmount,
uint256 oldDebtEntryFunding,
uint256 newDebtCollateralAmount,
uint256 newInflightDebtCollateralAmount,
uint256 newPendingFeeCollateralAmount,
uint256 newDebtEntryFunding
);
function onPlacePositionOrder(
address proxyOwner,
IGmxV2Adatper.OrderCreateParams calldata createParams,
IGmxV2Adatper.PositionResult calldata result
) external;
function onPlaceLiquidateOrder(address proxyOwner, IGmxV2Adatper.PositionResult calldata result) external;
function onBorrowCollateral(address proxyOwner, IGmxV2Adatper.DebtResult calldata result) external;
function onRepayCollateral(address proxyOwner, IGmxV2Adatper.DebtResult calldata result) external;
function onUpdateOrder(
address proxyOwner,
bytes32 key,
uint256 sizeDeltaUsd,
uint256 acceptablePrice,
uint256 triggerPrice
) external;
function onCancelOrder(address proxyOwner, bytes32 key) external;
function onUpdateDebt(
address proxyOwner,
bytes32 key,
uint256 oldDebtCollateralAmount, // collateral decimals
uint256 oldInflightDebtCollateralAmount, // collateral decimals
uint256 oldPendingFeeCollateralAmount, // collateral decimals
uint256 oldDebtEntryFunding,
uint256 newDebtCollateralAmount, // collateral decimals
uint256 newInflightDebtCollateralAmount, // collateral decimals
uint256 newPendingFeeCollateralAmount, // collateral decimals
uint256 newDebtEntryFunding
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableMapUpgradeable.sol";
import "./gmx/IOrder.sol";
address constant WETH = address(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1);
uint256 constant PROJECT_ID = 2;
uint256 constant VIRTUAL_ASSET_ID = 255;
uint8 constant POSITION_MARKET_ORDER = 0x40;
uint8 constant POSITION_TPSL_ORDER = 0x08;
interface IGmxV2Adatper {
enum ProjectConfigIds {
SWAP_ROUTER,
EXCHANGE_ROUTER,
ORDER_VAULT,
DATA_STORE,
REFERRAL_STORE,
READER,
PRICE_HUB,
EVENT_EMITTER,
REFERRAL_CODE,
FUNDING_ASSET_ID,
FUNDING_ASSET,
LIMIT_ORDER_EXPIRED_SECONDS,
END
}
enum MarketConfigIds {
BOOST_FEE_RATE,
INITIAL_MARGIN_RATE,
MAINTENANCE_MARGIN_RATE,
LIQUIDATION_FEE_RATE,
EMERGENCY_SWAP_SLIPPAGE,
INDEX_DECIMALS,
IS_BOOSTABLE,
END
}
enum OrderCategory {
Open,
Close,
TakeProfit,
StopLoss,
Liquidate
}
struct OrderRecord {
bool isIncreasing;
uint64 timestamp;
uint256 blockNumber;
uint256 collateralAmount;
uint256 debtCollateralAmount;
}
struct PendingOrder {
bytes32 key;
uint256 debtCollateralAmount;
uint256 timestamp;
uint256 blockNumber;
bool isIncreasing;
}
struct GmxAdapterStoreV2 {
// =========
address factory;
address liquidityPool;
bytes32 positionKey;
// ==========
uint32 projectConfigVersion;
uint32 marketConfigVersion;
uint8 shortTokenDecimals;
uint8 longTokenDecimals;
uint8 collateralTokenDecimals;
ProjectConfigs projectConfigs;
MarketConfigs marketConfigs;
AccountState account;
mapping(bytes32 => OrderRecord) pendingOrders;
EnumerableSetUpgradeable.Bytes32Set pendingOrderIndexes;
bytes32[50] __gaps;
}
struct ProjectConfigs {
address swapRouter;
address exchangeRouter;
address orderVault;
address dataStore;
address referralStore;
address reader;
address priceHub;
address eventEmitter;
bytes32 referralCode;
uint8 fundingAssetId;
address fundingAsset;
uint256 limitOrderExpiredSeconds;
bytes32[9] reserved;
}
struct MarketConfigs {
uint32 boostFeeRate;
uint32 initialMarginRate;
uint32 maintenanceMarginRate;
uint32 liquidationFeeRate; // an extra fee rate for liquidation
uint32 deleted0;
uint8 indexDecimals;
bool isBoostable;
bytes32[10] reserved;
}
struct AccountState {
address owner;
address market;
address indexToken;
address longToken;
address shortToken;
address collateralToken;
bool isLong;
// --------------------------
uint256 debtCollateralAmount; // collateral decimals
uint256 inflightDebtCollateralAmount; // collateral decimals
uint256 pendingFeeCollateralAmount; // collateral decimals
uint256 debtEntryFunding;
bool isLiquidating;
bytes32[10] reserved;
}
struct OrderCreateParams {
bytes swapPath;
uint256 initialCollateralAmount;
uint256 tokenOutMinAmount;
uint256 borrowCollateralAmount;
uint256 sizeDeltaUsd;
uint256 triggerPrice;
uint256 acceptablePrice;
uint256 executionFee;
uint256 callbackGasLimit;
IOrder.OrderType orderType;
}
struct Prices {
uint256 collateralPrice;
uint256 indexTokenPrice;
uint256 longTokenPrice;
uint256 shortTokenPrice;
}
struct PositionResult {
Prices prices;
address gasToken;
uint256 collateralAmount;
uint256 borrowedCollateralAmount;
bytes32 orderKey;
}
struct DebtResult {
// common
Prices prices;
// repay
uint256 collateralBalance;
uint256 secondaryTokenBalance;
uint256 debtCollateralAmount;
// fee
uint256 fundingFeeCollateralAmount;
uint256 boostFeeCollateralAmount;
uint256 liquidationFeeCollateralAmount;
uint256 totalFeeCollateralAmount;
// result
uint256 repaidDebtCollateralAmount;
uint256 repaidFeeCollateralAmount;
uint256 repaidDebtSecondaryTokenAmount;
uint256 repaidFeeSecondaryTokenAmount;
uint256 unpaidDebtCollateralAmount;
uint256 unpaidFeeCollateralAmount;
// refund
uint256 refundCollateralAmount;
uint256 refundSecondaryTokenAmount;
// borrow
uint256 borrowedCollateralAmount;
}
function muxAccountState() external view returns (AccountState memory);
function getPendingOrders() external view returns (PendingOrder[] memory pendingOrders);
function placeOrder(OrderCreateParams memory createParams) external payable returns (bytes32);
function updateOrder(bytes32 key, uint256 sizeDeltaUsd, uint256 acceptablePrice, uint256 triggerPrice) external;
function cancelOrder(bytes32 key) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "../../../interfaces/IProxyFactory.sol";
import "../interfaces/IGmxV2Adatper.sol";
import "../libraries/LibUtils.sol";
library LibConfig {
using LibUtils for uint256;
function updateConfigs(IGmxV2Adatper.GmxAdapterStoreV2 storage store) internal {
address market = store.account.market;
(uint32 remoteProjectVersion, uint32 remoteMarketVersion) = IProxyFactory(store.factory).getConfigVersions(
PROJECT_ID,
market
);
if (store.projectConfigVersion < remoteProjectVersion) {
updateProjectConfigs(store);
store.projectConfigVersion = remoteProjectVersion;
}
// pull configs from factory
if (store.marketConfigVersion < remoteMarketVersion) {
updateMarketConfigs(store, market);
store.marketConfigVersion = remoteMarketVersion;
}
}
function updateProjectConfigs(IGmxV2Adatper.GmxAdapterStoreV2 storage store) public {
uint256[] memory values = IProxyFactory(store.factory).getProjectConfig(PROJECT_ID);
require(values.length >= uint256(IGmxV2Adatper.ProjectConfigIds.END), "MissingConfigs");
store.projectConfigs.swapRouter = values[uint256(IGmxV2Adatper.ProjectConfigIds.SWAP_ROUTER)].toAddress();
store.projectConfigs.exchangeRouter = values[uint256(IGmxV2Adatper.ProjectConfigIds.EXCHANGE_ROUTER)]
.toAddress();
store.projectConfigs.orderVault = values[uint256(IGmxV2Adatper.ProjectConfigIds.ORDER_VAULT)].toAddress();
store.projectConfigs.dataStore = values[uint256(IGmxV2Adatper.ProjectConfigIds.DATA_STORE)].toAddress();
store.projectConfigs.referralStore = values[uint256(IGmxV2Adatper.ProjectConfigIds.REFERRAL_STORE)].toAddress();
store.projectConfigs.reader = values[uint256(IGmxV2Adatper.ProjectConfigIds.READER)].toAddress();
store.projectConfigs.priceHub = values[uint256(IGmxV2Adatper.ProjectConfigIds.PRICE_HUB)].toAddress();
store.projectConfigs.eventEmitter = values[uint256(IGmxV2Adatper.ProjectConfigIds.EVENT_EMITTER)].toAddress();
store.projectConfigs.referralCode = values[uint256(IGmxV2Adatper.ProjectConfigIds.REFERRAL_CODE)].toBytes32();
store.projectConfigs.fundingAssetId = values[uint256(IGmxV2Adatper.ProjectConfigIds.FUNDING_ASSET_ID)].toU8();
store.projectConfigs.fundingAsset = values[uint256(IGmxV2Adatper.ProjectConfigIds.FUNDING_ASSET)].toAddress();
store.projectConfigs.limitOrderExpiredSeconds = values[
uint256(IGmxV2Adatper.ProjectConfigIds.LIMIT_ORDER_EXPIRED_SECONDS)
];
}
function updateMarketConfigs(IGmxV2Adatper.GmxAdapterStoreV2 storage store, address market) public {
uint256[] memory values = IProxyFactory(store.factory).getProjectAssetConfig(PROJECT_ID, market);
require(values.length >= uint256(IGmxV2Adatper.MarketConfigIds.END), "MissingConfigs");
store.marketConfigs.boostFeeRate = values[uint256(IGmxV2Adatper.MarketConfigIds.BOOST_FEE_RATE)].toU32();
store.marketConfigs.initialMarginRate = values[uint256(IGmxV2Adatper.MarketConfigIds.INITIAL_MARGIN_RATE)]
.toU32();
store.marketConfigs.maintenanceMarginRate = values[
uint256(IGmxV2Adatper.MarketConfigIds.MAINTENANCE_MARGIN_RATE)
].toU32();
store.marketConfigs.liquidationFeeRate = values[uint256(IGmxV2Adatper.MarketConfigIds.LIQUIDATION_FEE_RATE)]
.toU32();
store.marketConfigs.indexDecimals = values[uint256(IGmxV2Adatper.MarketConfigIds.INDEX_DECIMALS)].toU8();
store.marketConfigs.isBoostable = values[uint256(IGmxV2Adatper.MarketConfigIds.IS_BOOSTABLE)] > 0;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "../../../interfaces/ILiquidityPool.sol";
import "../../../interfaces/IProxyFactory.sol";
import "../../../interfaces/ILendingPool.sol";
import "../../../interfaces/IWETH.sol";
import "../../../interfaces/IPriceHub.sol";
import "../interfaces/IGmxV2Adatper.sol";
import "../interfaces/IEventEmitter.sol";
import "./LibGmxV2.sol";
import "./LibUtils.sol";
library LibDebt {
using LibUtils for uint256;
using MathUpgradeable for uint256;
using SafeERC20Upgradeable for IERC20Upgradeable;
using LibGmxV2 for IGmxV2Adatper.GmxAdapterStoreV2;
using LibUtils for IGmxV2Adatper.GmxAdapterStoreV2;
uint56 internal constant ASSET_IS_STABLE = 0x00000000000001; // is stable
// implementations
function updateMuxFundingFee(IGmxV2Adatper.GmxAdapterStoreV2 storage store) internal returns (uint256) {
(uint256 fundingFee, uint256 nextFunding) = getNextMuxFunding(store);
store.account.pendingFeeCollateralAmount += fundingFee;
store.account.debtEntryFunding = nextFunding;
return fundingFee;
}
function getMuxFundingFee(
IGmxV2Adatper.GmxAdapterStoreV2 storage store
) internal view returns (uint256 fundingFee) {
(fundingFee, ) = getNextMuxFunding(store);
}
function getNextMuxFunding(
IGmxV2Adatper.GmxAdapterStoreV2 storage store
) internal view returns (uint256 fundingFee, uint256 newFunding) {
uint8 collateralId = IProxyFactory(store.factory).getAssetId(PROJECT_ID, store.account.collateralToken);
// is virtual
if (collateralId == VIRTUAL_ASSET_ID) {
fundingFee = 0;
newFunding = 0;
return (fundingFee, newFunding);
}
ILiquidityPool.Asset memory asset = ILiquidityPool(store.liquidityPool).getAssetInfo(collateralId);
if (asset.flags & ASSET_IS_STABLE == 0) {
// unstable
newFunding = asset.longCumulativeFundingRate; // 1e18
fundingFee = ((newFunding - store.account.debtEntryFunding) * store.account.debtCollateralAmount) / 1e18; // collateral.decimal
} else {
// stable
ILiquidityPool.Asset memory fundingAsset = ILiquidityPool(store.liquidityPool).getAssetInfo(
store.projectConfigs.fundingAssetId
);
newFunding = fundingAsset.shortCumulativeFunding; // 1e18
uint256 fundingTokenPrice = IPriceHub(store.projectConfigs.priceHub).getPriceByToken(
store.projectConfigs.fundingAsset
); // 1e18
fundingFee =
((newFunding - store.account.debtEntryFunding) * store.account.debtCollateralAmount) /
fundingTokenPrice; // collateral.decimal
}
}
function borrowCollateral(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
uint256 borrowCollateralAmount
) internal returns (uint256 borrowedCollateralAmount, uint256 boostFeeCollateralAmount) {
boostFeeCollateralAmount = (borrowCollateralAmount * store.marketConfigs.boostFeeRate) / 1e5;
borrowedCollateralAmount = borrowCollateralAmount - boostFeeCollateralAmount;
borrow(store, borrowCollateralAmount, boostFeeCollateralAmount);
store.account.debtCollateralAmount += borrowCollateralAmount;
}
function repayCancelledDebt(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
uint256 totalCollateralAmount,
uint256 debtCollateralAmount
) internal {
IGmxV2Adatper.DebtResult memory result;
result.fundingFeeCollateralAmount = updateMuxFundingFee(store);
result.collateralBalance = IERC20Upgradeable(store.account.collateralToken).balanceOf(address(this));
require(result.collateralBalance >= totalCollateralAmount, "NotEnoughBalance");
(
result.refundCollateralAmount,
result.repaidDebtCollateralAmount,
result.repaidFeeCollateralAmount
) = repayCancelledCollateral(store, debtCollateralAmount, totalCollateralAmount);
transferTokenToOwner(store, store.account.collateralToken, result.refundCollateralAmount);
}
function repayCancelledCollateral(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
uint256 debtCollateralAmount,
uint256 balance
)
internal
returns (uint256 toUserCollateralAmount, uint256 repayCollateralAmount, uint256 boostFeeCollateralAmount)
{
toUserCollateralAmount = balance;
if (debtCollateralAmount > 0) {
// return collateral
repayCollateralAmount = store.account.debtCollateralAmount.min(debtCollateralAmount);
require(balance >= repayCollateralAmount, "InsufficientBalance");
store.account.debtCollateralAmount -= repayCollateralAmount;
toUserCollateralAmount -= repayCollateralAmount;
// pay fee
boostFeeCollateralAmount = repayCollateralAmount.rate(store.marketConfigs.boostFeeRate);
if (toUserCollateralAmount >= boostFeeCollateralAmount) {
// pay fee this time
toUserCollateralAmount -= boostFeeCollateralAmount;
} else {
// pay fee next time
store.account.pendingFeeCollateralAmount += boostFeeCollateralAmount;
boostFeeCollateralAmount = 0;
}
repay(store, store.account.collateralToken, repayCollateralAmount, boostFeeCollateralAmount, 0);
}
}
function refundTokens(IGmxV2Adatper.GmxAdapterStoreV2 storage store) internal {
uint256 collateralBalance = IERC20Upgradeable(store.account.collateralToken).balanceOf(address(this));
transferTokenToOwner(store, store.account.collateralToken, collateralBalance);
address secondaryToken = store.getSecondaryToken();
if (store.account.collateralToken != secondaryToken) {
uint256 secondaryTokenBalance = IERC20Upgradeable(secondaryToken).balanceOf(address(this));
transferTokenToOwner(store, secondaryToken, secondaryTokenBalance);
}
store.account.isLiquidating = false;
}
function repayDebt(IGmxV2Adatper.GmxAdapterStoreV2 storage store, IGmxV2Adatper.Prices memory prices) internal {
IGmxV2Adatper.DebtResult memory result;
if (store.account.collateralToken == WETH) {
IWETH(WETH).deposit{ value: address(this).balance }();
}
// 1. get oracle price and gmx position
uint256 sizeInUsd = IReaderLite(store.projectConfigs.reader).getPositionSizeInUsd(
store.projectConfigs.dataStore,
store.positionKey
);
result.prices = prices;
// 2. get balance in proxy
result.fundingFeeCollateralAmount = updateMuxFundingFee(store);
result.collateralBalance = IERC20Upgradeable(store.account.collateralToken).balanceOf(address(this));
if (sizeInUsd != 0) {
if (store.isOpenSafe(result.prices, 0, 0)) {
result.refundCollateralAmount = result.collateralBalance;
transferTokenToOwner(store, store.account.collateralToken, result.refundCollateralAmount);
}
} else {
// totalDebt
result.debtCollateralAmount =
store.account.debtCollateralAmount -
store.account.inflightDebtCollateralAmount;
// totalFee
result.boostFeeCollateralAmount = result.debtCollateralAmount.rate(store.marketConfigs.boostFeeRate);
if (store.account.isLiquidating) {
result.liquidationFeeCollateralAmount = result.debtCollateralAmount.rate(
store.marketConfigs.liquidationFeeRate
);
}
result.totalFeeCollateralAmount =
result.boostFeeCollateralAmount +
store.account.pendingFeeCollateralAmount +
result.liquidationFeeCollateralAmount;
// repay by collateral
result = repayByCollateral(store, result);
// check secondary token
address secondaryToken = store.getSecondaryToken();
result.secondaryTokenBalance = IERC20Upgradeable(secondaryToken).balanceOf(address(this));
if (result.unpaidDebtCollateralAmount > 0 || result.unpaidFeeCollateralAmount > 0) {
// if there is secondary token, but debt has not been fully repaid
// try repay left debt with secondary token ...
result = repayBySecondaryToken(store, result, secondaryToken);
} else {
// or give all secondary token back to user
result.refundSecondaryTokenAmount = result.secondaryTokenBalance;
}
store.account.debtCollateralAmount = store.account.inflightDebtCollateralAmount;
store.account.pendingFeeCollateralAmount = 0;
transferTokenToOwner(store, store.account.collateralToken, result.refundCollateralAmount);
transferTokenToOwner(store, secondaryToken, result.refundSecondaryTokenAmount);
store.account.isLiquidating = false;
}
IEventEmitter(store.projectConfigs.eventEmitter).onRepayCollateral(store.account.owner, result);
}
function repayByCollateral(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.DebtResult memory result
) internal returns (IGmxV2Adatper.DebtResult memory) {
// 0. total fee to repay
result.refundCollateralAmount = result.collateralBalance;
// 1. pay the debt, missing part will be turned into bad debt
result.repaidDebtCollateralAmount = result.debtCollateralAmount.min(result.refundCollateralAmount);
result.refundCollateralAmount -= result.repaidDebtCollateralAmount;
// 2. pay the fee, if possible
if (result.refundCollateralAmount > 0) {
result.repaidFeeCollateralAmount = result.refundCollateralAmount.min(result.totalFeeCollateralAmount);
result.refundCollateralAmount -= result.repaidFeeCollateralAmount;
}
result.unpaidDebtCollateralAmount = result.debtCollateralAmount - result.repaidDebtCollateralAmount;
result.unpaidFeeCollateralAmount = result.totalFeeCollateralAmount - result.repaidFeeCollateralAmount;
repay(
store,
store.account.collateralToken,
result.repaidDebtCollateralAmount,
result.repaidFeeCollateralAmount,
0
);
return result;
}
function repayBySecondaryToken(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.DebtResult memory result,
address secondaryToken
) internal returns (IGmxV2Adatper.DebtResult memory) {
if (result.secondaryTokenBalance == 0) {
return result;
}
uint256 collateralPrice = result.prices.collateralPrice;
uint256 secondaryPrice = secondaryToken == store.account.longToken
? result.prices.longTokenPrice
: result.prices.shortTokenPrice;
uint8 collateralDecimals = store.collateralTokenDecimals;
uint8 secondaryDecimals = IERC20MetadataUpgradeable(secondaryToken).decimals();
uint256 debtSecondaryAmount = ((result.unpaidDebtCollateralAmount * collateralPrice) / secondaryPrice)
.toDecimals(collateralDecimals, secondaryDecimals);
result.repaidDebtSecondaryTokenAmount = result.secondaryTokenBalance.min(debtSecondaryAmount);
result.refundSecondaryTokenAmount = result.secondaryTokenBalance - result.repaidDebtSecondaryTokenAmount;
if (result.refundSecondaryTokenAmount > 0) {
uint256 debtFeeSecondaryAmount = ((result.unpaidFeeCollateralAmount * collateralPrice) / secondaryPrice)
.toDecimals(collateralDecimals, secondaryDecimals);
result.repaidFeeSecondaryTokenAmount = result.refundSecondaryTokenAmount.min(debtFeeSecondaryAmount);
result.refundSecondaryTokenAmount -= result.repaidFeeSecondaryTokenAmount;
}
result.unpaidDebtCollateralAmount -=
(result.repaidDebtSecondaryTokenAmount.toDecimals(secondaryDecimals, collateralDecimals) * secondaryPrice) /
collateralPrice;
result.unpaidFeeCollateralAmount -=
(result.repaidFeeSecondaryTokenAmount.toDecimals(secondaryDecimals, collateralDecimals) * secondaryPrice) /
collateralPrice;
repay(
store,
secondaryToken,
result.repaidDebtSecondaryTokenAmount,
result.repaidFeeSecondaryTokenAmount,
result.unpaidDebtCollateralAmount
);
return result;
}
// virtual methods
function borrow(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
uint256 amount,
uint256 fee
) internal returns (uint256 amountOut) {
amountOut = IProxyFactory(store.factory).borrowAsset(PROJECT_ID, store.account.collateralToken, amount, fee);
}
function repay(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
address token,
uint256 debtAmount,
uint256 feeAmount,
uint256 badDebt
) internal {
IERC20Upgradeable(token).safeTransfer(store.factory, debtAmount + feeAmount);
IProxyFactory(store.factory).repayAsset(PROJECT_ID, token, debtAmount, feeAmount, badDebt);
}
function transferTokenToOwner(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
address token,
uint256 amount
) internal {
if (amount == 0) {
return;
}
// TODO: send failed try/catch
if (token == WETH) {
IWETH(WETH).withdraw(amount);
payable(store.account.owner).transfer(amount);
} else {
IERC20Upgradeable(token).safeTransfer(store.account.owner, amount);
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "../../../interfaces/IWETH.sol";
import "../interfaces/gmx/IReader.sol";
import "../interfaces/gmx/IDataStore.sol";
import "../interfaces/gmx/IExchangeRouter.sol";
import "../interfaces/IGmxV2Adatper.sol";
import "../interfaces/IEventEmitter.sol";
import "./LibSwap.sol";
import "./LibDebt.sol";
import "./LibUtils.sol";
library LibGmxV2 {
using SafeERC20Upgradeable for IERC20Upgradeable;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set;
using LibSwap for IGmxV2Adatper.GmxAdapterStoreV2;
using LibDebt for IGmxV2Adatper.GmxAdapterStoreV2;
using LibUtils for IGmxV2Adatper.GmxAdapterStoreV2;
using LibUtils for uint256;
uint256 constant MAX_ORDER_COUNT = 32;
struct GmxPositionInfo {
uint256 collateralAmount;
uint256 sizeInUsd;
uint256 totalCostAmount;
int256 pnlAfterPriceImpactUsd;
}
// ===================================== READ =============================================
function getMarginValueUsd(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
uint256 collateralAmount,
uint256 totalCostAmount,
int256 pnlAfterPriceImpactUsd,
uint256 collateralPrice
) internal view returns (uint256) {
int256 collateralUsd = int256(
((collateralAmount * collateralPrice) / 1e18).toDecimals(store.collateralTokenDecimals, 30)
); // to 30
int256 gmxPnlUsd = pnlAfterPriceImpactUsd;
int256 gmxCostUsd = int256(
(totalCostAmount * collateralPrice).toDecimals(store.collateralTokenDecimals + 18, 30)
); // to 30
uint256 muxDebt = store.account.debtCollateralAmount +
store.account.pendingFeeCollateralAmount +
store.getMuxFundingFee() -
store.account.inflightDebtCollateralAmount;
int256 muxDebtUsd = int256(((muxDebt * collateralPrice) / 1e18).toDecimals(store.collateralTokenDecimals, 30)); // to 30
int256 marginValueUsd = collateralUsd + gmxPnlUsd - gmxCostUsd - muxDebtUsd;
return marginValueUsd >= 0 ? uint256(marginValueUsd) : 0; // truncate to 0
}
function makeGmxPrices(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.Prices memory prices
) internal view returns (IMarket.MarketPrices memory) {
uint256 indexTokenPrice = prices.indexTokenPrice.toDecimals(18, 30 - store.marketConfigs.indexDecimals);
uint256 longTokenPrice = prices.longTokenPrice.toDecimals(18, 30 - store.longTokenDecimals);
uint256 shortTokenPrice = prices.shortTokenPrice.toDecimals(18, 30 - store.shortTokenDecimals);
return
IMarket.MarketPrices({
indexTokenPrice: IPrice.Props({ max: indexTokenPrice, min: indexTokenPrice }),
longTokenPrice: IPrice.Props({ max: longTokenPrice, min: longTokenPrice }),
shortTokenPrice: IPrice.Props({ max: shortTokenPrice, min: shortTokenPrice })
});
}
// 1e18
function getMarginRate(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.Prices memory prices
) public view returns (uint256) {
uint256 sizeInUsd = IReaderLite(store.projectConfigs.reader).getPositionSizeInUsd(
store.projectConfigs.dataStore,
store.positionKey
);
if (sizeInUsd == 0) {
return 0;
}
GmxPositionInfo memory info;
(info.collateralAmount, info.sizeInUsd, info.totalCostAmount, info.pnlAfterPriceImpactUsd) = IReaderLite(
store.projectConfigs.reader
).getPositionMarginInfo(
store.projectConfigs.dataStore,
store.projectConfigs.referralStore,
store.positionKey,
makeGmxPrices(store, prices)
);
uint256 marginValueUsd = getMarginValueUsd(
store,
info.collateralAmount,
info.totalCostAmount,
info.pnlAfterPriceImpactUsd,
prices.collateralPrice
);
return ((marginValueUsd) * 1e18) / (info.sizeInUsd);
}
function isMarginSafe(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.Prices memory prices,
uint256 deltaCollateralAmount, // without delta debt
uint256 deltaSizeUsd,
uint256 marginRateThreshold // 1e18
) public view returns (bool) {
if (!store.marketConfigs.isBoostable) {
return true;
}
uint256 sizeInUsd = IReaderLite(store.projectConfigs.reader).getPositionSizeInUsd(
store.projectConfigs.dataStore,
store.positionKey
);
if (sizeInUsd > 0) {
GmxPositionInfo memory info;
(info.collateralAmount, info.sizeInUsd, info.totalCostAmount, info.pnlAfterPriceImpactUsd) = IReaderLite(
store.projectConfigs.reader
).getPositionMarginInfo(
store.projectConfigs.dataStore,
store.projectConfigs.referralStore,
store.positionKey,
makeGmxPrices(store, prices)
);
uint256 marginUsd = getMarginValueUsd(
store,
info.collateralAmount,
info.totalCostAmount,
info.pnlAfterPriceImpactUsd,
prices.collateralPrice
); // 1e30
if (marginUsd == 0) {
// already bankrupt
return false;
}
uint256 collateralUsd = ((deltaCollateralAmount * prices.collateralPrice) / 1e18).toDecimals(
store.collateralTokenDecimals,
30
);
uint256 nextMarginRate = ((marginUsd + collateralUsd) * 1e30) / (sizeInUsd + deltaSizeUsd) / 1e12; // 1e18
if (nextMarginRate < marginRateThreshold) {
return false;
}
} else {
if (deltaSizeUsd == 0) {
return true;
}
uint256 collateralUsd = ((deltaCollateralAmount * prices.collateralPrice) / 1e18).toDecimals(
store.collateralTokenDecimals,
30
);
uint256 nextMarginRate = ((collateralUsd) * 1e30) / (deltaSizeUsd) / 1e12; // 1e18
if (nextMarginRate < marginRateThreshold) {
return false;
}
}
return true;
}
function isOpenSafe(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.Prices memory prices,
uint256 deltaCollateralAmount, // without delta debt
uint256 deltaSizeUsd
) public view returns (bool) {
return
isMarginSafe(
store,
prices,
deltaCollateralAmount,
deltaSizeUsd,
uint256(store.marketConfigs.initialMarginRate) * 1e13
);
}
function isCloseSafe(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.Prices memory prices
) public view returns (bool) {
return isMarginSafe(store, prices, 0, 0, uint256(store.marketConfigs.maintenanceMarginRate) * 1e13);
}
// ===================================== WRITE =============================================
function openPosition(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.OrderCreateParams memory createParams
) external returns (bytes32) {
require(store.pendingOrderIndexes.length() < MAX_ORDER_COUNT, "ExceedsMaxOrderCount");
IGmxV2Adatper.PositionResult memory result;
// swap
if (createParams.swapPath.length != 0) {
// swap tokenIn => collateral
result.collateralAmount = store.swapCollateral(
createParams.swapPath,
createParams.initialCollateralAmount,
createParams.tokenOutMinAmount,
address(this)
);
} else {
// no swap
result.collateralAmount = createParams.initialCollateralAmount;
}
if (store.marketConfigs.isBoostable) {
result.prices = store.getOraclePrices(); // check account safe
require(
isOpenSafe(store, result.prices, result.collateralAmount, createParams.sizeDeltaUsd),
"UnsafeToOpen"
);
}
// borrow
if (createParams.borrowCollateralAmount > 0) {
require(store.marketConfigs.isBoostable, "NotBoostable");
result.borrowedCollateralAmount = borrowCollateral(
store,
result.prices,
createParams.borrowCollateralAmount
);
}
// place order
uint256 totalCollateralAmount = result.collateralAmount + result.borrowedCollateralAmount;
// execution fee
IERC20Upgradeable(store.account.collateralToken).safeTransfer(
store.projectConfigs.orderVault,
totalCollateralAmount
);
createParams.initialCollateralAmount = totalCollateralAmount;
// primary order
result.orderKey = placeOrder(store, createParams);
store.appendOrder(result.orderKey, totalCollateralAmount, createParams.borrowCollateralAmount, true);
IEventEmitter(store.projectConfigs.eventEmitter).onPlacePositionOrder(
store.account.owner,
createParams,
result
);
return result.orderKey;
}
function closePosition(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.OrderCreateParams memory createParams
) external returns (bytes32) {
require(store.pendingOrderIndexes.length() < MAX_ORDER_COUNT, "ExceedsMaxOrderCount");
require(createParams.swapPath.length == 0, "SwapPathNotAvailable");
// price
IGmxV2Adatper.PositionResult memory result;
if (store.marketConfigs.isBoostable) {
result.prices = store.getOraclePrices();
require(isCloseSafe(store, result.prices), "MarginUnsafe");
}
result.collateralAmount = createParams.initialCollateralAmount;
// place order
result.orderKey = placeOrder(store, createParams);
store.appendOrder(result.orderKey);
IEventEmitter(store.projectConfigs.eventEmitter).onPlacePositionOrder(
store.account.owner,
createParams,
result
);
return result.orderKey;
}
function liquidatePosition(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.Prices memory prices,
uint256 executionFee,
uint256 callbackGasLimit
) external {
require(executionFee == msg.value, "WrongExecutionFee");
IWETH(WETH).deposit{ value: executionFee }();
IGmxV2Adatper.PositionResult memory result;
result.prices = prices;
result = placeLiquidateOrder(store, executionFee, callbackGasLimit, result);
IEventEmitter(store.projectConfigs.eventEmitter).onPlaceLiquidateOrder(store.account.owner, result);
}
function placeLiquidateOrder(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
uint256 executionFee,
uint256 callbackGasLimit,
IGmxV2Adatper.PositionResult memory result
) internal returns (IGmxV2Adatper.PositionResult memory) {
// if no position, no need to liquidate
uint256 sizeInUsd = IReaderLite(store.projectConfigs.reader).getPositionSizeInUsd(
store.projectConfigs.dataStore,
store.positionKey
);
require(sizeInUsd > 0, "NoPositionToLiquidate");
// if position is safe, no need to liquidate
require(!isCloseSafe(store, result.prices), "MarginSafe");
// place market liquidate order
result.orderKey = placeOrder(
store,
IGmxV2Adatper.OrderCreateParams({
swapPath: "",
initialCollateralAmount: 0,
tokenOutMinAmount: 0,
borrowCollateralAmount: 0,
sizeDeltaUsd: sizeInUsd,
triggerPrice: 0,
acceptablePrice: store.account.isLong ? 0 : type(uint256).max,
executionFee: executionFee,
callbackGasLimit: callbackGasLimit,
orderType: IOrder.OrderType.MarketDecrease
})
);
store.appendOrder(result.orderKey);
store.account.isLiquidating = true;
return result;
}
function placeOrder(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.OrderCreateParams memory orderParams
) internal returns (bytes32 orderKey) {
address exchangeRouter = store.projectConfigs.exchangeRouter;
require(exchangeRouter != address(0), "ExchangeRouterUnset");
// execution fee (weth)
IERC20Upgradeable(WETH).safeTransfer(store.projectConfigs.orderVault, orderParams.executionFee);
// place order
orderKey = IExchangeRouter(store.projectConfigs.exchangeRouter).createOrder(
IExchangeRouter.CreateOrderParams({
addresses: IExchangeRouter.CreateOrderParamsAddresses({
receiver: address(this),
callbackContract: address(this),
uiFeeReceiver: address(0),
market: store.account.market,
initialCollateralToken: store.account.collateralToken,
swapPath: new address[](0)
}),
numbers: IExchangeRouter.CreateOrderParamsNumbers({
sizeDeltaUsd: orderParams.sizeDeltaUsd,
initialCollateralDeltaAmount: orderParams.initialCollateralAmount,
triggerPrice: orderParams.triggerPrice,
acceptablePrice: orderParams.acceptablePrice,
executionFee: orderParams.executionFee,
callbackGasLimit: orderParams.callbackGasLimit,
minOutputAmount: 0
}),
orderType: orderParams.orderType,
decreasePositionSwapType: IOrder.DecreasePositionSwapType.SwapPnlTokenToCollateralToken,
isLong: store.account.isLong,
shouldUnwrapNativeToken: false,
referralCode: store.projectConfigs.referralCode
})
);
}
function updateOrder(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
bytes32 key,
uint256 sizeDeltaUsd,
uint256 acceptablePrice,
uint256 triggerPrice
) external {
address exchangeRouter = store.projectConfigs.exchangeRouter;
require(exchangeRouter != address(0), "ExchangeRouterUnset");
IExchangeRouter(exchangeRouter).updateOrder(key, sizeDeltaUsd, acceptablePrice, triggerPrice, 0);
IEventEmitter(store.projectConfigs.eventEmitter).onUpdateOrder(
store.account.owner,
key,
sizeDeltaUsd,
acceptablePrice,
triggerPrice
);
}
function cancelOrder(IGmxV2Adatper.GmxAdapterStoreV2 storage store, bytes32 key) external {
if (store.pendingOrderIndexes.contains(key)) {
cancelOrder(store, key, false);
}
}
function cancelExpiredOrder(IGmxV2Adatper.GmxAdapterStoreV2 storage store, bytes32 key) external {
if (store.pendingOrderIndexes.contains(key)) {
IGmxV2Adatper.OrderRecord memory record = store.pendingOrders[key];
require(
record.isIncreasing &&
block.timestamp > record.timestamp + store.projectConfigs.limitOrderExpiredSeconds,
"NotExpired"
);
cancelOrder(store, key, false);
}
}
function cancelOrder(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
bytes32 key,
bool ignoreFailure
) internal returns (bool) {
address exchangeRouter = store.projectConfigs.exchangeRouter;
require(exchangeRouter != address(0), "ExchangeRouterUnset");
try IExchangeRouter(exchangeRouter).cancelOrder(key) {
return true;
} catch {
require(ignoreFailure, "CancelOrderFailed");
return false;
}
}
function borrowCollateral(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
IGmxV2Adatper.Prices memory prices,
uint256 borrowCollateralAmount
) internal returns (uint256 borrowedCollateralAmount) {
IGmxV2Adatper.DebtResult memory result;
result.prices = prices;
result.fundingFeeCollateralAmount = store.updateMuxFundingFee();
(result.borrowedCollateralAmount, result.boostFeeCollateralAmount) = store.borrowCollateral(
borrowCollateralAmount
);
borrowedCollateralAmount = result.borrowedCollateralAmount;
IEventEmitter(store.projectConfigs.eventEmitter).onBorrowCollateral(store.account.owner, result);
}
function claimToken(IGmxV2Adatper.GmxAdapterStoreV2 storage store, address token) internal returns (uint256) {
uint256 sizeInUsd = IReaderLite(store.projectConfigs.reader).getPositionSizeInUsd(
store.projectConfigs.dataStore,
store.positionKey
);
require(sizeInUsd == 0 && store.account.debtCollateralAmount == 0, "NotAllowed");
uint256 balance = IERC20Upgradeable(token).balanceOf(address(this));
IERC20Upgradeable(token).safeTransfer(store.account.owner, balance);
return balance;
}
function isOrderExist(IGmxV2Adatper.GmxAdapterStoreV2 storage store, bytes32 key) external view returns (bool) {
return IReaderLite(store.projectConfigs.reader).isOrderExist(store.projectConfigs.dataStore, key);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "../../../interfaces/IPriceHub.sol";
import "../interfaces/IGmxV2Adatper.sol";
library LibSwap {
using SafeERC20Upgradeable for IERC20Upgradeable;
function swapCollateral(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
bytes memory swapPath,
uint256 amountIn,
uint256 minAmountOut,
address recipient
) internal returns (uint256 amountOut) {
address tokenIn = decodeInputToken(swapPath);
require(tokenIn != store.account.collateralToken, "IllegalTokenIn");
amountOut = swap(store, swapPath, tokenIn, amountIn, minAmountOut, recipient);
}
function swap(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
bytes memory swapPath,
address tokenIn,
uint256 amountIn,
uint256 minAmountOut,
address recipient
) internal returns (uint256 amountOut) {
address swapRouter = store.projectConfigs.swapRouter;
require(swapRouter != address(0), "swapRouterUnset");
// exact input swap to convert exact amount of tokens into usdc
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: swapPath,
recipient: recipient,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: minAmountOut
});
// executes the swap on uniswap pool
IERC20Upgradeable(tokenIn).approve(store.projectConfigs.swapRouter, amountIn);
// since exact input swap tokens used = token amount passed
amountOut = ISwapRouter(store.projectConfigs.swapRouter).exactInput(params);
}
// function emergencySwap(
// IGmxV2Adatper.GmxAdapterStoreV2 storage store,
// bytes memory swapPath,
// address tokenIn,
// uint256 totalBalance,
// uint256 expAmountOut,
// uint256 minAmountOut,
// address recipient
// ) external returns (uint256 amountIn, uint256 amountOut) {
// address swapRouter = store.projectConfigs.swapRouter;
// require(swapRouter != address(0), "swapRouterUnset");
// IERC20Upgradeable(tokenIn).approve(swapRouter, totalBalance);
// ISwapRouter.ExactOutputParams memory exactOutParams = ISwapRouter.ExactOutputParams({
// path: swapPath,
// recipient: recipient,
// deadline: block.timestamp,
// amountOut: expAmountOut,
// amountInMaximum: totalBalance
// });
// try ISwapRouter(swapRouter).exactOutput(exactOutParams) returns (uint256 amountIn_) {
// amountIn = amountIn_;
// amountOut = expAmountOut;
// } catch {
// // uint256 minAmountOut = (amountOut * (1e18 - slippageTolerance)) / 1e18;
// ISwapRouter.ExactInputParams memory exactInParams = ISwapRouter.ExactInputParams({
// path: swapPath,
// recipient: recipient,
// deadline: block.timestamp,
// amountIn: amountIn,
// amountOutMinimum: minAmountOut
// });
// // executes the swap on uniswap pool
// IERC20Upgradeable(tokenIn).approve(swapRouter, amountIn);
// // since exact input swap tokens used = token amount passed
// amountOut = ISwapRouter(swapRouter).exactInput(exactInParams);
// amountIn = totalBalance;
// }
// }
function decodeInputToken(bytes memory _bytes) internal pure returns (address) {
require(_bytes.length >= 20, "outOfBounds");
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), 0)), 0x1000000000000000000000000)
}
return tempAddress;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
import "../../../interfaces/IProxyFactory.sol";
import "../../../interfaces/IArbSys.sol";
import "../../../interfaces/IPriceHub.sol";
import "../interfaces/IGmxV2Adatper.sol";
import "../interfaces/gmx/IMarket.sol";
import "../interfaces/gmx/IReaderLite.sol";
library LibUtils {
using SafeERC20Upgradeable for IERC20Upgradeable;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set;
uint256 internal constant RATE_DENOMINATOR = 1e5;
address internal constant ARB_SYS = address(100);
uint256 internal constant ARBITRUM_CHAIN_ID = 42161;
function toDecimals(uint256 n, uint8 decimalsFrom, uint8 decimalsTo) internal pure returns (uint256) {
if (decimalsFrom > decimalsTo) {
return n / (10 ** (decimalsFrom - decimalsTo));
} else if (decimalsFrom < decimalsTo) {
return n * (10 ** (decimalsTo - decimalsFrom));
} else {
return n;
}
}
function toAddress(bytes32 value) internal pure returns (address) {
return address(bytes20(value));
}
function toAddress(uint256 value) internal pure returns (address) {
return address(bytes20(bytes32(value)));
}
function toBytes32(uint256 value) internal pure returns (bytes32) {
return bytes32(value);
}
function toU256(address value) internal pure returns (uint256) {
return uint256(bytes32(bytes20(uint160(value))));
}
function toU32(bytes32 value) internal pure returns (uint32) {
require(uint256(value) <= type(uint32).max, "OU32");
return uint32(uint256(value));
}
function toU32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "OU32");
return uint32(value);
}
function toU8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "OU8");
return uint8(value);
}
function toU96(uint256 n) internal pure returns (uint96) {
require(n <= type(uint96).max, "OU96"); // uint96 Overflow
return uint96(n);
}
function rate(uint256 value, uint32 rate_) internal pure returns (uint256) {
return (value * rate_) / RATE_DENOMINATOR;
}
function setupTokens(IGmxV2Adatper.GmxAdapterStoreV2 storage store, address collateralToken) internal {
(, address indexToken, address longToken, address shortToken) = IReaderLite(store.projectConfigs.reader)
.getMarketTokens(store.projectConfigs.dataStore, store.account.market);
store.account.indexToken = indexToken;
store.account.longToken = longToken;
store.account.shortToken = shortToken;
store.account.collateralToken = collateralToken;
store.collateralTokenDecimals = IERC20MetadataUpgradeable(collateralToken).decimals();
store.longTokenDecimals = IERC20MetadataUpgradeable(longToken).decimals();
store.shortTokenDecimals = IERC20MetadataUpgradeable(shortToken).decimals();
require(
collateralToken == store.account.longToken || collateralToken == store.account.shortToken,
"InvalidToken"
);
}
function getOraclePrices(
IGmxV2Adatper.GmxAdapterStoreV2 storage store
) internal view returns (IGmxV2Adatper.Prices memory prices) {
IPriceHub priceHub = IPriceHub(store.projectConfigs.priceHub);
prices.indexTokenPrice = priceHub.getPriceByToken(store.account.indexToken);
prices.longTokenPrice = priceHub.getPriceByToken(store.account.longToken);
prices.shortTokenPrice = priceHub.getPriceByToken(store.account.shortToken);
prices.collateralPrice = store.account.collateralToken == store.account.longToken
? prices.longTokenPrice
: prices.shortTokenPrice;
}
function getSecondaryToken(IGmxV2Adatper.GmxAdapterStoreV2 storage store) internal view returns (address) {
if (store.account.collateralToken == store.account.longToken) {
return store.account.shortToken;
} else {
return store.account.longToken;
}
}
function claimNativeToken(IGmxV2Adatper.GmxAdapterStoreV2 storage store) internal returns (uint256) {
if (store.account.collateralToken != WETH) {
uint256 balance = address(this).balance;
AddressUpgradeable.sendValue(payable(store.account.owner), balance);
return balance;
} else {
return 0;
}
}
function appendOrder(IGmxV2Adatper.GmxAdapterStoreV2 storage store, bytes32 key) internal {
appendOrder(store, key, 0, 0, false);
}
function appendOrder(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
bytes32 key,
uint256 collateralAmount, // collateral + debt
uint256 debtCollateralAmount,
bool isIncreasing
) internal {
store.pendingOrders[key] = IGmxV2Adatper.OrderRecord({
isIncreasing: isIncreasing,
timestamp: uint64(block.timestamp),
blockNumber: getBlockNumber(),
collateralAmount: collateralAmount,
debtCollateralAmount: debtCollateralAmount
});
store.pendingOrderIndexes.add(key);
store.account.inflightDebtCollateralAmount += debtCollateralAmount;
}
function removeOrder(
IGmxV2Adatper.GmxAdapterStoreV2 storage store,
bytes32 key
) internal returns (IGmxV2Adatper.OrderRecord memory orderRecord) {
// main order
// \_ store.tpOrderKeys => tp order
// \_ store.slOrderKeys => sl order
orderRecord = store.pendingOrders[key];
uint256 debtCollateralAmount = orderRecord.debtCollateralAmount;
delete store.pendingOrders[key];
store.pendingOrderIndexes.remove(key);
store.account.inflightDebtCollateralAmount -= debtCollateralAmount;
}
function getBlockNumber() internal view returns (uint256) {
if (block.chainid == ARBITRUM_CHAIN_ID) {
return IArbSys(address(100)).arbBlockNumber();
}
return block.number;
}
function setupCallback(IGmxV2Adatper.GmxAdapterStoreV2 storage store) internal {
IExchangeRouter(store.projectConfigs.exchangeRouter).setSavedCallbackContract(
store.account.market,
address(this)
);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableMapUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./interfaces/IGmxV2Adatper.sol";
abstract contract Storage is IGmxV2Adatper {
GmxAdapterStoreV2 internal _store;
bytes32[50] private __gaps;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
contract ImplementationGuard {
address private immutable _this;
constructor() {
_this = address(this);
}
modifier onlyDelegateCall() {
require(address(this) != _this);
_;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IArbSys {
function arbBlockNumber() external view returns (uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
uint256 constant STATE_IS_ENABLED = 0x1;
uint256 constant STATE_IS_BORROWABLE = 0x2;
uint256 constant STATE_IS_REPAYABLE = 0x4;
uint256 constant STATE_IS_DEPOSITABLE = 0x8;
uint256 constant STATE_IS_WITHDRAWABLE = 0x10;
interface ILendingPool {
struct BorrowState {
uint256 flags;
uint256 supplyAmount;
uint256 borrowFeeAmount;
uint256 totalAmountOut;
uint256 totalAmountIn;
uint256 badDebtAmount;
bytes32[10] __reserves;
}
struct LendingPoolStore {
address priceHub;
address swapRouter;
address liquidityPool;
uint256 totalBorrowUsd;
uint256 totalRepayUsd;
mapping(address => uint256) borrowUsds;
mapping(address => uint256) repayUsds;
mapping(address => bool) borrowers;
mapping(address => bool) maintainers;
mapping(address => BorrowState) borrowStates;
bytes32[50] __reserves;
}
event BorrowToken(address indexed borrower, address indexed token, uint256 borrowAmount, uint256 borrowFee);
event RepayToken(
address indexed repayer,
address indexed token,
uint256 repayAmount,
uint256 borrowFee,
uint256 badDebt
);
event SetMaintainer(address indexed maintainer, bool enabled);
event SetBorrower(address indexed borrower, bool enabled);
event SetSwapRouter(address indexed swapRouter);
event SetFlags(address indexed token, uint256 enables, uint256 disables, uint256 result);
event Deposit(address indexed token, uint256 amount);
event Withdraw(address indexed token, uint256 amount);
event ClaimFee(address indexed token, address recipient, uint256 amount);
function borrowToken(
uint256 projectId,
address borrower,
address token,
uint256 borrowAmount,
uint256 borrowFee
) external returns (uint256);
function repayToken(
uint256 projectId,
address repayer,
address token,
uint256 repayAmount,
uint256 borrowFee,
uint256 badDebt
) external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface ILiquidityPool {
struct Asset {
// slot
// assets with the same symbol in different chains are the same asset. they shares the same muxToken. so debts of the same symbol
// can be accumulated across chains (see Reader.AssetState.deduct). ex: ERC20(fBNB).symbol should be "BNB", so that BNBs of
// different chains are the same.
// since muxToken of all stable coins is the same and is calculated separately (see Reader.ChainState.stableDeduct), stable coin
// symbol can be different (ex: "USDT", "USDT.e" and "fUSDT").
bytes32 symbol;
// slot
address tokenAddress; // erc20.address
uint8 id;
uint8 decimals; // erc20.decimals
uint56 flags; // a bitset of ASSET_*
uint24 _flagsPadding;
// slot
uint32 initialMarginRate; // 1e5
uint32 maintenanceMarginRate; // 1e5
uint32 minProfitRate; // 1e5
uint32 minProfitTime; // 1e0
uint32 positionFeeRate; // 1e5
// note: 96 bits remaining
// slot
address referenceOracle;
uint32 referenceDeviation; // 1e5
uint8 referenceOracleType;
uint32 halfSpread; // 1e5
// note: 24 bits remaining
// slot
uint96 credit;
uint128 _reserved2;
// slot
uint96 collectedFee;
uint32 liquidationFeeRate; // 1e5
uint96 spotLiquidity;
// note: 32 bits remaining
// slot
uint96 maxLongPositionSize;
uint96 totalLongPosition;
// note: 64 bits remaining
// slot
uint96 averageLongPrice;
uint96 maxShortPositionSize;
// note: 64 bits remaining
// slot
uint96 totalShortPosition;
uint96 averageShortPrice;
// note: 64 bits remaining
// slot, less used
address muxTokenAddress; // muxToken.address. all stable coins share the same muxTokenAddress
uint32 spotWeight; // 1e0
uint32 longFundingBaseRate8H; // 1e5
uint32 longFundingLimitRate8H; // 1e5
// slot
uint128 longCumulativeFundingRate; // Σ_t fundingRate_t
uint128 shortCumulativeFunding; // Σ_t fundingRate_t * indexPrice_t
}
function borrowAsset(address borrower, uint8 assetId, uint256 rawAmount, uint256 rawFee) external returns (uint256);
function repayAsset(
address repayer,
uint8 assetId,
uint256 rawAmount,
uint256 rawFee,
uint256 rawBadDebt // debt amount that cannot be recovered
) external;
function getAssetAddress(uint8 assetId) external view returns (address);
function getLiquidityPoolStorage()
external
view
returns (
// [0] shortFundingBaseRate8H
// [1] shortFundingLimitRate8H
// [2] lastFundingTime
// [3] fundingInterval
// [4] liquidityBaseFeeRate
// [5] liquidityDynamicFeeRate
// [6] sequence. note: will be 0 after 0xffffffff
// [7] strictStableDeviation
uint32[8] memory u32s,
// [0] mlpPriceLowerBound
// [1] mlpPriceUpperBound
uint96[2] memory u96s
);
function getAssetInfo(uint8 assetId) external view returns (Asset memory);
function setLiquidityManager(address liquidityManager, bool enable) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.17;
interface IMuxOrderBook {
struct PositionOrderExtra {
// tp/sl strategy
uint96 tpPrice; // take-profit price. decimals = 18. only valid when flags.POSITION_TPSL_STRATEGY.
uint96 slPrice; // stop-loss price. decimals = 18. only valid when flags.POSITION_TPSL_STRATEGY.
uint8 tpslProfitTokenId; // only valid when flags.POSITION_TPSL_STRATEGY.
uint32 tpslDeadline; // only valid when flags.POSITION_TPSL_STRATEGY.
}
/**
* @notice Liquidity Order can be filled after this time in seconds.
*/
function liquidityLockPeriod() external view returns (uint32);
/**
* @notice Market Order MUST NOT be filled after this time in seconds.
*/
function marketOrderTimeout() external view returns (uint32);
/**
* @notice Limit/Trigger Order MUST NOT be filled after this time in seconds.
*/
function maxLimitOrderTimeout() external view returns (uint32);
/**
* @notice Return true if the filling of position order is temporarily paused.
*/
function isPositionOrderPaused() external view returns (bool);
/**
* @notice Return true if the filling of liquidity/rebalance order is temporarily paused.
*/
function isLiquidityOrderPaused() external view returns (bool);
/**
* @notice Get an Order by orderId.
*/
function getOrder(uint64 orderId) external view returns (bytes32[3] memory, bool);
/**
* @notice Get more parameters (ex: tp/sl strategy parameters) of a position order by orderId.
*/
function positionOrderExtras(uint64 orderId) external view returns (PositionOrderExtra memory);
/**
* @notice Cancel an Order by orderId.
*/
function cancelOrder(uint64 orderId) external;
/**
* @notice Open/close position. called by Trader.
*
* Market order will expire after marketOrderTimeout seconds.
* Limit/Trigger order will expire after deadline.
* @param subAccountId sub account id. see LibSubAccount.decodeSubAccountId.
* @param collateralAmount deposit collateral before open; or withdraw collateral after close. decimals = erc20.decimals.
* @param size position size. decimals = 18.
* @param price limit price. decimals = 18.
* @param profitTokenId specify the profitable asset.id when closing a position and making a profit.
* take no effect when opening a position or loss.
* @param flags a bitset of LibOrder.POSITION_*.
* POSITION_OPEN this flag means openPosition; otherwise closePosition
* POSITION_MARKET_ORDER this flag means ignore limitPrice
* POSITION_WITHDRAW_ALL_IF_EMPTY this flag means auto withdraw all collateral if position.size == 0
* POSITION_TRIGGER_ORDER this flag means this is a trigger order (ex: stop-loss order). otherwise this is a limit order (ex: take-profit order)
* @param deadline a unix timestamp after which the limit/trigger order MUST NOT be filled. fill 0 for market order.
* @param referralCode set referral code of the trading account.
*/
function placePositionOrder2(
bytes32 subAccountId,
uint96 collateralAmount, // erc20.decimals
uint96 size, // 1e18
uint96 price, // 1e18
uint8 profitTokenId,
uint8 flags,
uint32 deadline, // 1e0
bytes32 referralCode
) external payable;
function placePositionOrder3(
bytes32 subAccountId,
uint96 collateralAmount, // erc20.decimals
uint96 size, // 1e18
uint96 price, // 1e18
uint8 profitTokenId,
uint8 flags,
uint32 deadline, // 1e0
bytes32 referralCode,
PositionOrderExtra memory extra
) external payable;
/**
* @notice Add/remove liquidity. called by Liquidity Provider.
*
* Can be filled after liquidityLockPeriod seconds.
* @param assetId asset.id that added/removed to.
* @param rawAmount asset token amount. decimals = erc20.decimals.
* @param isAdding true for add liquidity, false for remove liquidity.
*/
function placeLiquidityOrder(
uint8 assetId,
uint96 rawAmount, // erc20.decimals
bool isAdding
) external payable;
/**
* @notice Withdraw collateral/profit. called by Trader.
*
* This order will expire after marketOrderTimeout seconds.
* @param subAccountId sub account id. see LibSubAccount.decodeSubAccountId.
* @param rawAmount collateral or profit asset amount. decimals = erc20.decimals.
* @param profitTokenId specify the profitable asset.id.
* @param isProfit true for withdraw profit. false for withdraw collateral.
*/
function placeWithdrawalOrder(
bytes32 subAccountId,
uint96 rawAmount, // erc20.decimals
uint8 profitTokenId,
bool isProfit
) external;
/**
* @notice Rebalance pool liquidity. Swap token 0 for token 1.
*
* msg.sender must implement IMuxRebalancerCallback.
* @param tokenId0 asset.id to be swapped out of the pool.
* @param tokenId1 asset.id to be swapped into the pool.
* @param rawAmount0 token 0 amount. decimals = erc20.decimals.
* @param maxRawAmount1 max token 1 that rebalancer is willing to pay. decimals = erc20.decimals.
* @param userData any user defined data.
*/
function placeRebalanceOrder(
uint8 tokenId0,
uint8 tokenId1,
uint96 rawAmount0, // erc20.decimals
uint96 maxRawAmount1, // erc20.decimals
bytes32 userData
) external;
function setAggregator(address aggregatorAddress, bool isEnable) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IPriceHub {
function getPriceByToken(address token) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "../interfaces/IMuxOrderBook.sol";
interface IProxyFactory {
struct OpenPositionArgsV2 {
uint256 projectId;
address collateralToken;
address assetToken;
bool isLong;
address tokenIn;
uint256 amountIn; // tokenIn.decimals
uint256 minOut; // collateral.decimals
uint256 borrow; // collateral.decimals
uint256 sizeUsd; // 1e18
uint96 priceUsd; // 1e18
uint96 tpPriceUsd; // 1e18
uint96 slPriceUsd; // 1e18
uint8 flags; // MARKET, TRIGGER
bytes32 referralCode;
}
struct ClosePositionArgsV2 {
uint256 projectId;
address collateralToken;
address assetToken;
bool isLong;
uint256 collateralUsd; // collateral.decimals
uint256 sizeUsd; // 1e18
uint96 priceUsd; // 1e18
uint96 tpPriceUsd; // 1e18
uint96 slPriceUsd; // 1e18
uint8 flags; // MARKET, TRIGGER
bytes32 referralCode;
}
struct MuxOrderParams {
bytes32 subAccountId;
uint96 collateralAmount; // erc20.decimals
uint96 size; // 1e18
uint96 price; // 1e18
uint8 profitTokenId;
uint8 flags;
uint32 deadline; // 1e0
bytes32 referralCode;
IMuxOrderBook.PositionOrderExtra extra;
}
struct PositionOrderExtra {
// tp/sl strategy
uint96 tpPrice; // take-profit price. decimals = 18. only valid when flags.POSITION_TPSL_STRATEGY.
uint96 slPrice; // stop-loss price. decimals = 18. only valid when flags.POSITION_TPSL_STRATEGY.
uint8 tpslProfitTokenId; // only valid when flags.POSITION_TPSL_STRATEGY.
uint32 tpslDeadline; // only valid when flags.POSITION_TPSL_STRATEGY.
}
struct OrderParams {
bytes32 orderKey;
uint256 collateralDelta;
uint256 sizeDelta;
uint256 triggerPrice;
bool triggerAboveThreshold;
}
struct ProxyCallParams {
uint256 projectId;
address collateralToken;
address assetToken;
bool isLong;
bytes32 referralCode;
uint256 value;
bytes proxyCallData;
}
event SetMaintainer(address maintainer, bool enable);
event SetKeeper(address keeper, bool enable);
event SetBorrowConfig(
uint256 projectId,
address assetToken,
uint8 prevAssetId,
uint8 newAssetId,
uint256 prevLimit,
uint256 newLimit
);
event DisableBorrowConfig(uint256 projectId, address assetToken);
event MuxCall(address target, uint256 value, bytes data);
event SetLiquiditySource(uint256 indexed projectId, uint256 sourceId, address source);
function weth() external view returns (address);
function getProxiesOf(address account) external view returns (address[] memory);
function isKeeper(address keeper) external view returns (bool);
function getProjectConfig(uint256 projectId) external view returns (uint256[] memory);
function getProjectAssetConfig(uint256 projectId, address assetToken) external view returns (uint256[] memory);
function getBorrowStates(
uint256 projectId,
address assetToken
) external view returns (uint256 totalBorrow, uint256 borrowLimit, uint256 badDebt);
function getAssetId(uint256 projectId, address token) external view returns (uint8);
function getConfigVersions(
uint256 projectId,
address assetToken
) external view returns (uint32 projectConfigVersion, uint32 assetConfigVersion);
function getProxyProjectId(address proxy) external view returns (uint256);
function getLiquiditySource(uint256 projectId) external view returns (uint256 sourceId, address source);
function borrowAsset(
uint256 projectId,
address collateralToken,
uint256 amount,
uint256 fee
) external returns (uint256 amountOut);
function repayAsset(
uint256 projectId,
address collateralToken,
uint256 amount,
uint256 fee,
uint256 badDebt_
) external;
}//SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IWETH {
function deposit() external payable;
function approve(address spender, uint256 value) external;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
function balanceOf(address) external view returns (uint256);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {
"contracts/aggregators/gmxV2/libraries/LibGmxV2.sol": {
"LibGmxV2": "0x426ded3b3dc4971951d900e50b79564c3601f88d"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"address","name":"uiFeeReceiver","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"initialCollateralToken","type":"address"},{"internalType":"address[]","name":"swapPath","type":"address[]"}],"internalType":"struct IOrder.Addresses","name":"addresses","type":"tuple"},{"components":[{"internalType":"enum IOrder.OrderType","name":"orderType","type":"uint8"},{"internalType":"enum IOrder.DecreasePositionSwapType","name":"decreasePositionSwapType","type":"uint8"},{"internalType":"uint256","name":"sizeDeltaUsd","type":"uint256"},{"internalType":"uint256","name":"initialCollateralDeltaAmount","type":"uint256"},{"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"internalType":"uint256","name":"acceptablePrice","type":"uint256"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"},{"internalType":"uint256","name":"updatedAtBlock","type":"uint256"}],"internalType":"struct IOrder.Numbers","name":"numbers","type":"tuple"},{"components":[{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"bool","name":"shouldUnwrapNativeToken","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct IOrder.Flags","name":"flags","type":"tuple"}],"internalType":"struct IOrder.Props","name":"","type":"tuple"},{"components":[{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"}],"internalType":"struct IEvent.AddressKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address[]","name":"value","type":"address[]"}],"internalType":"struct IEvent.AddressArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.AddressItems","name":"addressItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IEvent.UintKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256[]","name":"value","type":"uint256[]"}],"internalType":"struct IEvent.UintArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.UintItems","name":"uintItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"int256","name":"value","type":"int256"}],"internalType":"struct IEvent.IntKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"int256[]","name":"value","type":"int256[]"}],"internalType":"struct IEvent.IntArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.IntItems","name":"intItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"}],"internalType":"struct IEvent.BoolKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool[]","name":"value","type":"bool[]"}],"internalType":"struct IEvent.BoolArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.BoolItems","name":"boolItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes32","name":"value","type":"bytes32"}],"internalType":"struct IEvent.Bytes32KeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes32[]","name":"value","type":"bytes32[]"}],"internalType":"struct IEvent.Bytes32ArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.Bytes32Items","name":"bytes32Items","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct IEvent.BytesKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes[]","name":"value","type":"bytes[]"}],"internalType":"struct IEvent.BytesArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.BytesItems","name":"bytesItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"internalType":"struct IEvent.StringKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string[]","name":"value","type":"string[]"}],"internalType":"struct IEvent.StringArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.StringItems","name":"stringItems","type":"tuple"}],"internalType":"struct IEvent.EventLogData","name":"","type":"tuple"}],"name":"afterOrderCancellation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"address","name":"uiFeeReceiver","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"initialCollateralToken","type":"address"},{"internalType":"address[]","name":"swapPath","type":"address[]"}],"internalType":"struct IOrder.Addresses","name":"addresses","type":"tuple"},{"components":[{"internalType":"enum IOrder.OrderType","name":"orderType","type":"uint8"},{"internalType":"enum IOrder.DecreasePositionSwapType","name":"decreasePositionSwapType","type":"uint8"},{"internalType":"uint256","name":"sizeDeltaUsd","type":"uint256"},{"internalType":"uint256","name":"initialCollateralDeltaAmount","type":"uint256"},{"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"internalType":"uint256","name":"acceptablePrice","type":"uint256"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"},{"internalType":"uint256","name":"updatedAtBlock","type":"uint256"}],"internalType":"struct IOrder.Numbers","name":"numbers","type":"tuple"},{"components":[{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"bool","name":"shouldUnwrapNativeToken","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct IOrder.Flags","name":"flags","type":"tuple"}],"internalType":"struct IOrder.Props","name":"","type":"tuple"},{"components":[{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"}],"internalType":"struct IEvent.AddressKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address[]","name":"value","type":"address[]"}],"internalType":"struct IEvent.AddressArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.AddressItems","name":"addressItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IEvent.UintKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256[]","name":"value","type":"uint256[]"}],"internalType":"struct IEvent.UintArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.UintItems","name":"uintItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"int256","name":"value","type":"int256"}],"internalType":"struct IEvent.IntKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"int256[]","name":"value","type":"int256[]"}],"internalType":"struct IEvent.IntArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.IntItems","name":"intItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"}],"internalType":"struct IEvent.BoolKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool[]","name":"value","type":"bool[]"}],"internalType":"struct IEvent.BoolArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.BoolItems","name":"boolItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes32","name":"value","type":"bytes32"}],"internalType":"struct IEvent.Bytes32KeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes32[]","name":"value","type":"bytes32[]"}],"internalType":"struct IEvent.Bytes32ArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.Bytes32Items","name":"bytes32Items","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct IEvent.BytesKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes[]","name":"value","type":"bytes[]"}],"internalType":"struct IEvent.BytesArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.BytesItems","name":"bytesItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"internalType":"struct IEvent.StringKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string[]","name":"value","type":"string[]"}],"internalType":"struct IEvent.StringArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.StringItems","name":"stringItems","type":"tuple"}],"internalType":"struct IEvent.EventLogData","name":"","type":"tuple"}],"name":"afterOrderExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"address","name":"uiFeeReceiver","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"initialCollateralToken","type":"address"},{"internalType":"address[]","name":"swapPath","type":"address[]"}],"internalType":"struct IOrder.Addresses","name":"addresses","type":"tuple"},{"components":[{"internalType":"enum IOrder.OrderType","name":"orderType","type":"uint8"},{"internalType":"enum IOrder.DecreasePositionSwapType","name":"decreasePositionSwapType","type":"uint8"},{"internalType":"uint256","name":"sizeDeltaUsd","type":"uint256"},{"internalType":"uint256","name":"initialCollateralDeltaAmount","type":"uint256"},{"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"internalType":"uint256","name":"acceptablePrice","type":"uint256"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"},{"internalType":"uint256","name":"updatedAtBlock","type":"uint256"}],"internalType":"struct IOrder.Numbers","name":"numbers","type":"tuple"},{"components":[{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"bool","name":"shouldUnwrapNativeToken","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct IOrder.Flags","name":"flags","type":"tuple"}],"internalType":"struct IOrder.Props","name":"","type":"tuple"},{"components":[{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"}],"internalType":"struct IEvent.AddressKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address[]","name":"value","type":"address[]"}],"internalType":"struct IEvent.AddressArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.AddressItems","name":"addressItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IEvent.UintKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256[]","name":"value","type":"uint256[]"}],"internalType":"struct IEvent.UintArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.UintItems","name":"uintItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"int256","name":"value","type":"int256"}],"internalType":"struct IEvent.IntKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"int256[]","name":"value","type":"int256[]"}],"internalType":"struct IEvent.IntArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.IntItems","name":"intItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"}],"internalType":"struct IEvent.BoolKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool[]","name":"value","type":"bool[]"}],"internalType":"struct IEvent.BoolArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.BoolItems","name":"boolItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes32","name":"value","type":"bytes32"}],"internalType":"struct IEvent.Bytes32KeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes32[]","name":"value","type":"bytes32[]"}],"internalType":"struct IEvent.Bytes32ArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.Bytes32Items","name":"bytes32Items","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct IEvent.BytesKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes[]","name":"value","type":"bytes[]"}],"internalType":"struct IEvent.BytesArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.BytesItems","name":"bytesItems","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"internalType":"struct IEvent.StringKeyValue[]","name":"items","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string[]","name":"value","type":"string[]"}],"internalType":"struct IEvent.StringArrayKeyValue[]","name":"arrayItems","type":"tuple[]"}],"internalType":"struct IEvent.StringItems","name":"stringItems","type":"tuple"}],"internalType":"struct IEvent.EventLogData","name":"","type":"tuple"}],"name":"afterOrderFrozen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"cancelExpiredOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"cancelOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"markets","type":"address[]"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"claimFundingFees","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimNativeToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"claimToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"collateralPrice","type":"uint256"},{"internalType":"uint256","name":"indexTokenPrice","type":"uint256"},{"internalType":"uint256","name":"longTokenPrice","type":"uint256"},{"internalType":"uint256","name":"shortTokenPrice","type":"uint256"}],"internalType":"struct IGmxV2Adatper.Prices","name":"prices","type":"tuple"}],"name":"getMarginRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingOrders","outputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"uint256","name":"debtCollateralAmount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bool","name":"isIncreasing","type":"bool"}],"internalType":"struct IGmxV2Adatper.PendingOrder[]","name":"pendingOrders","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId_","type":"uint256"},{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"bool","name":"isLong","type":"bool"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"collateralPrice","type":"uint256"},{"internalType":"uint256","name":"indexTokenPrice","type":"uint256"},{"internalType":"uint256","name":"longTokenPrice","type":"uint256"},{"internalType":"uint256","name":"shortTokenPrice","type":"uint256"}],"internalType":"struct IGmxV2Adatper.Prices","name":"prices","type":"tuple"}],"name":"isLiquidateable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"collateralPrice","type":"uint256"},{"internalType":"uint256","name":"indexTokenPrice","type":"uint256"},{"internalType":"uint256","name":"longTokenPrice","type":"uint256"},{"internalType":"uint256","name":"shortTokenPrice","type":"uint256"}],"internalType":"struct IGmxV2Adatper.Prices","name":"prices","type":"tuple"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"}],"name":"liquidatePosition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"muxAccountState","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"indexToken","type":"address"},{"internalType":"address","name":"longToken","type":"address"},{"internalType":"address","name":"shortToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"uint256","name":"debtCollateralAmount","type":"uint256"},{"internalType":"uint256","name":"inflightDebtCollateralAmount","type":"uint256"},{"internalType":"uint256","name":"pendingFeeCollateralAmount","type":"uint256"},{"internalType":"uint256","name":"debtEntryFunding","type":"uint256"},{"internalType":"bool","name":"isLiquidating","type":"bool"},{"internalType":"bytes32[10]","name":"reserved","type":"bytes32[10]"}],"internalType":"struct IGmxV2Adatper.AccountState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"swapPath","type":"bytes"},{"internalType":"uint256","name":"initialCollateralAmount","type":"uint256"},{"internalType":"uint256","name":"tokenOutMinAmount","type":"uint256"},{"internalType":"uint256","name":"borrowCollateralAmount","type":"uint256"},{"internalType":"uint256","name":"sizeDeltaUsd","type":"uint256"},{"internalType":"uint256","name":"triggerPrice","type":"uint256"},{"internalType":"uint256","name":"acceptablePrice","type":"uint256"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"},{"internalType":"enum IOrder.OrderType","name":"orderType","type":"uint8"}],"internalType":"struct IGmxV2Adatper.OrderCreateParams","name":"createParams","type":"tuple"}],"name":"placeOrder","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"positionKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"uint256","name":"sizeDeltaUsd","type":"uint256"},{"internalType":"uint256","name":"acceptablePrice","type":"uint256"},{"internalType":"uint256","name":"triggerPrice","type":"uint256"}],"name":"updateOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a060405234801561001057600080fd5b5030608052608051615a2b6200003160003960006110970152615a2b6000f3fe6080604052600436106101025760003560e01c80637489ec231161009557806390cdaaba1161006457806390cdaaba146102a15780639642a948146102c1578063b9091f22146102e3578063c74c54cf146102f6578063d219c26d1461031657600080fd5b80637489ec231461020f5780637c3506241461022f57806380bf219e146102515780638792e6211461028157600080fd5b80635102a708116100d15780635102a708146101a7578063573cdef4146101ba57806369e92224146101da578063715824e4146101fa57600080fd5b806325e4ac2b1461010e57806328bc2fca14610130578063299887dc1461015957806332f289cf1461017957600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012e610129366004613926565b61032b565b005b61014361013e366004613aee565b6103e1565b6040516101509190613b51565b60405180910390f35b34801561016557600080fd5b5061012e610174366004614aaa565b61046c565b34801561018557600080fd5b50610199610194366004614bfe565b61065d565b604051908152602001610150565b6101996101b5366004614c1b565b610669565b3480156101c657600080fd5b506101996101d5366004614d56565b6107a2565b3480156101e657600080fd5b5061012e6101f5366004614aaa565b61081f565b34801561020657600080fd5b50610199610848565b34801561021b57600080fd5b5061012e61022a366004613926565b610859565b34801561023b57600080fd5b506102446108f1565b6040516101509190614d72565b34801561025d57600080fd5b5061027161026c366004614d56565b610a6b565b6040519015158152602001610150565b34801561028d57600080fd5b5061012e61029c366004614de2565b610ba0565b3480156102ad57600080fd5b5061012e6102bc366004614aaa565b610c88565b3480156102cd57600080fd5b506102d6610da0565b6040516101509190614e37565b61012e6102f1366004614f37565b610e7b565b34801561030257600080fd5b5061012e610311366004614f6b565b610fcd565b34801561032257600080fd5b50600254610199565b602d5460ff16156103575760405162461bcd60e51b815260040161034e90614fe4565b60405180910390fd5b61035f611274565b61036960006112cd565b60405163660851a560e01b8152600060048201526024810182905273426ded3b3dc4971951d900e50b79564c3601f88d9063660851a5906044015b60006040518083038186803b1580156103bc57600080fd5b505af41580156103d0573d6000803e3d6000fd5b505050506103de600160a055565b50565b60055460235460405163c41b1ab360e01b81526060926001600160a01b039081169263c41b1ab39261041c928892889291169060040161504d565b6000604051808303816000875af115801561043b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610463919081019061508b565b90505b92915050565b6104746113d6565b6104905760405162461bcd60e51b815260040161034e90615110565b602954602a54602b54602c5460405163066659ff60e41b8152600060048201526024810188905273426ded3b3dc4971951d900e50b79564c3601f88d906366659ff090604401602060405180830381865af41580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610517919061513f565b156105555760405162461bcd60e51b815260206004820152600e60248201526d13dc99195c939bdd119a5b1b195960921b604482015260640161034e565b60006105618189611599565b805190915061059b576029541561059157600061057e6000611687565b905061058b60008261184e565b5061059b565b61059b6000611cc7565b6105a56000611e01565b50600b54602354602954602a54602b54602c546040516318a363dd60e11b81526001600160a01b039586166004820152602481018f9052604481018c9052606481018b9052608481018a905260a4810189905260c481019490945260e4840192909252610104830152610124820152911690633146c7ba9061014401600060405180830381600087803b15801561063b57600080fd5b505af115801561064f573d6000803e3d6000fd5b505050505050505050505050565b60006104668183611e4e565b6000610673611fb0565b61068f5760405162461bcd60e51b815260040161034e9061515c565b602d5460ff16156106b25760405162461bcd60e51b815260040161034e90614fe4565b6106ba611274565b6106c460006112cd565b6106d2826101200151611fe7565b15610759576040516353c151d160e01b815273426ded3b3dc4971951d900e50b79564c3601f88d906353c151d190610711906000908690600401615211565b602060405180830381865af415801561072e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075291906152ae565b9050610793565b60405163f774b64960e01b815273426ded3b3dc4971951d900e50b79564c3601f88d9063f774b64990610711906000908690600401615211565b61079d600160a055565b919050565b604051631c6abf2360e21b815260009073426ded3b3dc4971951d900e50b79564c3601f88d906371aafc8c906107de90849086906004016152c7565b602060405180830381865af41580156107fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046691906152ae565b6108276113d6565b6108435760405162461bcd60e51b815260040161034e90615110565b505050565b60006108546000611e01565b905090565b610861611fb0565b61087d5760405162461bcd60e51b815260040161034e9061515c565b602d5460ff16156108a05760405162461bcd60e51b815260040161034e90614fe4565b6108a8611274565b6108b260006112cd565b604051638e3f043560e01b8152600060048201526024810182905273426ded3b3dc4971951d900e50b79564c3601f88d90638e3f0435906044016103a4565b606060006108ff603961201f565b90508060000361090d575090565b806001600160401b038111156109255761092561393f565b60405190808252806020026020018201604052801561097e57816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282526000199092019101816109435790505b50915060005b81811015610a66576000610999603983612029565b600081815260386020908152604091829020825160a08082018552825460ff8116151583526001600160401b03610100909104811683860190815260018501548488019081526002860154606080870191909152600390960154608080870191825289519586018a528a86529051978501979097529051909116958201959095529351918401919091528051151591830191909152865192935091869085908110610a4657610a466152fc565b602002602001018190525050508080610a5e90615328565b915050610984565b505090565b6009546007546002546040516323e967a560e01b81526001600160a01b0392831660048201526024810191909152600092839216906323e967a590604401602060405180830381865afa158015610ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aea91906152ae565b905080600003610afd5750600092915050565b601854610b1d90600160401b900463ffffffff166509184e72a000615341565b604051631c6abf2360e21b815273426ded3b3dc4971951d900e50b79564c3601f88d906371aafc8c90610b579060009088906004016152c7565b602060405180830381865af4158015610b74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9891906152ae565b109392505050565b610ba8611fb0565b610bc45760405162461bcd60e51b815260040161034e9061515c565b602d5460ff1615610be75760405162461bcd60e51b815260040161034e90614fe4565b610bef611274565b610bf960006112cd565b60405163069dae5d60e01b8152600060048201526024810185905260448101849052606481018390526084810182905273426ded3b3dc4971951d900e50b79564c3601f88d9063069dae5d9060a40160006040518083038186803b158015610c6057600080fd5b505af4158015610c74573d6000803e3d6000fd5b50505050610c82600160a055565b50505050565b610c906113d6565b610cac5760405162461bcd60e51b815260040161034e90615110565b602954602a54602b54602c5460405163066659ff60e41b8152600060048201526024810188905273426ded3b3dc4971951d900e50b79564c3601f88d906366659ff090604401602060405180830381865af4158015610d0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d33919061513f565b15610d745760405162461bcd60e51b815260206004820152601160248201527013dc99195c939bdd10d85b98d95b1b1959607a1b604482015260640161034e565b6000610d808189611599565b80519091501561059b576060810151608082015161059b91600091612035565b610da86137e7565b604080516101a081018252602380546001600160a01b03908116835260245481166020840152602554811683850152602654811660608401526027548116608084015260285490811660a0840152600160a01b900460ff908116151560c084015260295460e0840152602a54610100840152602b54610120840152602c5461014080850191909152602d54909116151561016084015283519081019384905291929091610180840191602e90600a9082845b815481526020019060010190808311610e5a57505050505081525050905090565b6000546040516335d2155560e11b81523360048201526001600160a01b0390911690636ba42aaa90602401602060405180830381865afa158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee7919061513f565b610f205760405162461bcd60e51b815260206004820152600a60248201526937b7363ca5b2b2b832b960b11b604482015260640161034e565b602d5460ff1615610f435760405162461bcd60e51b815260040161034e90614fe4565b610f4b611274565b610f5560006112cd565b604051630762b6ed60e21b815273426ded3b3dc4971951d900e50b79564c3601f88d90631d8adbb490610f9390600090879087908790600401615358565b60006040518083038186803b158015610fab57600080fd5b505af4158015610fbf573d6000803e3d6000fd5b50505050610843600160a055565b609f54610100900460ff1615808015610fed5750609f54600160ff909116105b806110075750303b1580156110075750609f5460ff166001145b61106a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161034e565b609f805460ff19166001179055801561108d57609f805461ff0019166101001790555b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110c257600080fd5b6001600160a01b03861661110f5760405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a59131a5c5d5a591a5d1e541bdbdb60621b604482015260640161034e565b600287146111505760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59141c9bda9958dd60921b604482015260640161034e565b600080546001600160a01b03199081163317909155600180546001600160a01b038981169190931617905560408051306020820152858316918101919091529085166060820152821515608082015260a00160408051601f19818403018152919052805160209091012060025560288054831515600160a01b0260ff60a01b19909116179055602480546001600160a01b038086166001600160a01b031992831617909255602380549288169290911691909117905561121060006112cd565b61121b60008561213b565b6112256000612410565b801561126b57609f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b600260a054036112c65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161034e565b600260a055565b60248181015482546040516370693e1560e11b8152600260048201526001600160a01b039283169381018490526000928392169063e0d27c2a906044016040805180830381865afa158015611326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134a91906153b3565b6003860154919350915063ffffffff808416911610156113855761136d8461247b565b60038401805463ffffffff191663ffffffff84161790555b600384015463ffffffff808316640100000000909204161015610c82576113ac8484612771565b60038401805463ffffffff83166401000000000267ffffffff000000001990911617905550505050565b600080546040516335d2155560e11b81523360048201526001600160a01b0390911690636ba42aaa90602401602060405180830381865afa15801561141f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611443919061513f565b1561144e5750600190565b600754604080516312929ec160e21b815290516000926001600160a01b031691634a4a7b049160048281019260209291908290030181865afa158015611498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bc91906153f1565b9050806001600160a01b031663ac4ab3fb336040516020016114fc906020808252600a908201526921a7a72a2927a62622a960b11b604082015260600190565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b81526004016115439291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015611560573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611584919061513f565b1561159157600191505090565b600091505090565b6115d66040518060a0016040528060001515815260200160006001600160401b031681526020016000815260200160008152602001600081525090565b5060008181526038830160208181526040808420815160a081018352815460ff8116151582526001600160401b0361010082041682860152600183018054948301949094526002830180546060840152600384018054608085018190528a8a529790965268ffffffffffffffffff19909116909255918590558490559290556116626039850184612979565b508084602301600701600082825461167a919061540e565b9091555091949350505050565b6116b26040518060800160405280600081526020016000815260200160008152602001600081525090565b600a8201546025830154604051636047675960e01b81526001600160a01b0391821660048201529116908190636047675990602401602060405180830381865afa158015611704573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172891906152ae565b60208301526026830154604051636047675960e01b81526001600160a01b03918216600482015290821690636047675990602401602060405180830381865afa158015611779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179d91906152ae565b60408381019190915260278401549051636047675960e01b81526001600160a01b03918216600482015290821690636047675990602401602060405180830381865afa1580156117f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181591906152ae565b6060830152602683015460288401546001600160a01b03908116911614611840578160600151611846565b81604001515b825250919050565b61185661385a565b60288301546001600160a01b03167382af49447d8a07e3bd95bd0d56f35241523fbab019016118e8577382af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b1580156118ce57600080fd5b505af11580156118e2573d6000803e3d6000fd5b50505050505b6009830154600784015460028501546040516323e967a560e01b81526001600160a01b039283166004820152602481019190915260009291909116906323e967a590604401602060405180830381865afa15801561194a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196e91906152ae565b838352905061197c84612985565b608083015260288401546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156119cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ef91906152ae565b60208301528015611aaa578151604051631ed6ab2960e11b815273426ded3b3dc4971951d900e50b79564c3601f88d91633dad565291611a389188916000908190600401615358565b602060405180830381865af4158015611a55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a79919061513f565b15611aa55760208201516101c083018190526028850154611aa59186916001600160a01b0316906129c0565b611c55565b602a8401546029850154611abe919061540e565b606083018190526018850154611ade919063ffffffff90811690612aaf16565b60a0830152602d84015460ff1615611b1a5760188401546060830151611b149163ffffffff600160601b909104811690612aaf16565b60c08301525b60c0820151602b85015460a0840151611b339190615421565b611b3d9190615421565b60e0830152611b4c8483612acf565b91506000611b5985612bb2565b6040516370a0823160e01b81523060048201529091506001600160a01b038216906370a0823190602401602060405180830381865afa158015611ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc491906152ae565b6040840152610180830151151580611be157506000836101a00151115b15611bf857611bf1858483612bf3565b9250611c04565b60408301516101e08401525b602a85015460298601556000602b86015560288501546101c0840151611c379187916001600160a01b03909116906129c0565b611c478582856101e001516129c0565b50602d8401805460ff191690555b600b8401546023850154604051631bed973760e01b81526001600160a01b0392831692631bed973792611c8f929116908690600401615434565b600060405180830381600087803b158015611ca957600080fd5b505af1158015611cbd573d6000803e3d6000fd5b5050505050505050565b60288101546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611d12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3691906152ae565b6028830154909150611d539083906001600160a01b0316836129c0565b6000611d5e83612bb2565b60288401549091506001600160a01b03808316911614611df2576040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de391906152ae565b9050611df08483836129c0565b505b5050602d01805460ff19169055565b60288101546000906001600160a01b03167382af49447d8a07e3bd95bd0d56f35241523fbab114611e465760238201544790610466906001600160a01b031682612e11565b506000919050565b6009820154600783015460028401546040516323e967a560e01b81526001600160a01b0392831660048201526024810191909152600092839216906323e967a590604401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed391906152ae565b905080158015611ee557506029840154155b611f1e5760405162461bcd60e51b815260206004820152600a602482015269139bdd105b1b1bddd95960b21b604482015260640161034e565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8991906152ae565b6023860154909150611fa8906001600160a01b03868116911683612f2a565b949350505050565b600080546001600160a01b03163303611fc95750600190565b6023546001600160a01b03163303611fe15750600190565b50600090565b60006002826007811115611ffd57611ffd6151d9565b148061046657506003826007811115612018576120186151d9565b1492915050565b6000610466825490565b60006104638383612f7c565b61203d61385a565b61204684612985565b608082015260288401546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b991906152ae565b602082018190528311156121025760405162461bcd60e51b815260206004820152601060248201526f4e6f74456e6f75676842616c616e636560801b604482015260640161034e565b61210d848385612fa6565b6101208401526101008301526101c082018190526028850154610c829186916001600160a01b0316906129c0565b6009820154600783015460248085015460405163036226ff60e11b81526001600160a01b03938416600482015290831691810191909152600092839283929116906306c44dfe90604401608060405180830381865afa1580156121a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c6919061554d565b6025890180546001600160a01b038086166001600160a01b03199283161790925560268b01805483861690831617905560278b01805483851690831617905560288b018054928b1692909116821790556040805163313ce56760e01b81529051949850929650909450925063313ce5679160048281019260209291908290030181865afa15801561225b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227f91906155bd565b85600301600a6101000a81548160ff021916908360ff160217905550816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fd91906155bd565b8560030160096101000a81548160ff021916908360ff160217905550806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237b91906155bd565b60038601805460ff92909216600160401b0268ff00000000000000001990921691909117905560268501546001600160a01b03858116911614806123ce575060278501546001600160a01b038581169116145b6124095760405162461bcd60e51b815260206004820152600c60248201526b24b73b30b634b22a37b5b2b760a11b604482015260640161034e565b5050505050565b600581015460248083015460405163039fd84f60e11b81526001600160a01b03918216600482015230928101929092529091169063073fb09e90604401600060405180830381600087803b15801561246757600080fd5b505af1158015612409573d6000803e3d6000fd5b8054604051638947175b60e01b8152600260048201526000916001600160a01b031690638947175b90602401600060405180830381865afa1580156124c4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124ec919081019061508b565b9050600c815110156125315760405162461bcd60e51b815260206004820152600e60248201526d4d697373696e67436f6e6669677360901b604482015260640161034e565b6125568160005b81518110612548576125486152fc565b602002602001015160601c90565b6004830180546001600160a01b0319166001600160a01b0392909216919091179055612583816001612538565b6005830180546001600160a01b0319166001600160a01b03929092169190911790556125b0816002612538565b6006830180546001600160a01b0319166001600160a01b03929092169190911790556125dd816003612538565b6007830180546001600160a01b0319166001600160a01b039290921691909117905561260a816004612538565b6008830180546001600160a01b0319166001600160a01b0392909216919091179055612637816005612538565b6009830180546001600160a01b0319166001600160a01b0392909216919091179055612664816006612538565b600a830180546001600160a01b0319166001600160a01b0392909216919091179055612691816007612538565b600b830180546001600160a01b0319166001600160a01b03929092169190911790556126d4816008815181106126c9576126c96152fc565b602002602001015190565b600c8301556126fd8160095b815181106126f0576126f06152fc565b60200260200101516130ac565b600d8301805460ff191660ff9290921691909117905561271e81600a612538565b600d830180546001600160a01b039290921661010002610100600160a81b031990921691909117905580600b8151811061275a5761275a6152fc565b602002602001015182600401600a01819055505050565b8154604051633e65196f60e01b8152600260048201526001600160a01b0383811660248301526000921690633e65196f90604401600060405180830381865afa1580156127c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127ea919081019061508b565b905060078151101561282f5760405162461bcd60e51b815260206004820152600e60248201526d4d697373696e67436f6e6669677360901b604482015260640161034e565b6128538160005b81518110612846576128466152fc565b60200260200101516130e9565b60188401805463ffffffff191663ffffffff9290921691909117905561287a816001612836565b60188401805463ffffffff929092166401000000000267ffffffff00000000199092169190911790556128ae816002612836565b60188401805463ffffffff92909216600160401b026bffffffff0000000000000000199092169190911790556128e5816003612836565b60188401805463ffffffff92909216600160601b0263ffffffff60601b199092169190911790556129178160056126e0565b60188401805460ff92909216600160a01b0260ff60a01b1990921691909117905560008160068151811061294d5761294d6152fc565b6020026020010151118360180160000160156101000a81548160ff021916908315150217905550505050565b60006104638383613128565b60008060006129938461321b565b91509150818460230160080160008282546129ae9190615421565b9091555050602c909301929092555090565b806000036129cd57505050565b7382af49447d8a07e3bd95bd0d56f35241523fbab0196001600160a01b03831601612a9357604051632e1a7d4d60e01b8152600481018290527382af49447d8a07e3bd95bd0d56f35241523fbab190632e1a7d4d90602401600060405180830381600087803b158015612a3f57600080fd5b505af1158015612a53573d6000803e3d6000fd5b50505060238401546040516001600160a01b03909116915082156108fc029083906000818181858888f19350505050158015610c82573d6000803e3d6000fd5b6023830154610843906001600160a01b03848116911683612f2a565b6000620186a0612ac563ffffffff841685615341565b61046391906155d8565b612ad761385a565b60208201516101c083018190526060830151612af2916134c7565b61010083018190526101c083018051612b0c90839061540e565b9052506101c082015115612b4c5760e08201516101c0830151612b2e916134c7565b61012083018190526101c083018051612b4890839061540e565b9052505b8161010001518260600151612b61919061540e565b61018083015261012082015160e0830151612b7c919061540e565b6101a08301526028830154610100830151610120840151612bac9286926001600160a01b039091169160006134dd565b50919050565b602681015460288201546000916001600160a01b03908116911603612be25750602701546001600160a01b031690565b50602601546001600160a01b031690565b612bfb61385a565b8260400151600003612c0e575081612e0a565b82515160268501546000906001600160a01b03858116911614612c3657845160600151612c3d565b8451604001515b9050600086600301600a9054906101000a900460ff1690506000856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb991906155bd565b90506000612ce5838386888c6101800151612cd49190615341565b612cde91906155d8565b9190613588565b6040890151909150612cf790826134c7565b61014089018190526040890151612d0e919061540e565b6101e0890181905215612d66576000612d34848487898d6101a00151612cd49190615341565b6101e08a0151909150612d4790826134c7565b6101608a018190526101e08a018051612d6190839061540e565b905250505b61014088015185908590612d7b908587613588565b612d859190615341565b612d8f91906155d8565b8861018001818151612da1919061540e565b90525061016088015185908590612db9908587613588565b612dc39190615341565b612dcd91906155d8565b886101a001818151612ddf919061540e565b9052506101408801516101608901516101808a0151612e01928c928b926134dd565b87955050505050505b9392505050565b80471015612e615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161034e565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612eae576040519150601f19603f3d011682016040523d82523d6000602084013e612eb3565b606091505b50509050806108435760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161034e565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526108439084906135f2565b6000826000018281548110612f9357612f936152fc565b9060005260206000200154905092915050565b8060008084156130a3576029860154612fbf90866134c7565b9150818410156130075760405162461bcd60e51b8152602060048201526013602482015272496e73756666696369656e7442616c616e636560681b604482015260640161034e565b8186602301600601600082825461301e919061540e565b9091555061302e9050828461540e565b601887015490935061304b90839063ffffffff90811690612aaf16565b90508083106130655761305e818461540e565b9250613086565b8086602301600801600082825461307c9190615421565b9091555060009150505b60288601546130a39087906001600160a01b0316848460006134dd565b93509350939050565b600060ff8211156130e55760405162461bcd60e51b815260206004820152600360248201526209eaa760eb1b604482015260640161034e565b5090565b600063ffffffff8211156130e55760405162461bcd60e51b815260040161034e9060208082526004908201526327aa999960e11b604082015260600190565b6000818152600183016020526040812054801561321157600061314c60018361540e565b85549091506000906131609060019061540e565b90508181146131c5576000866000018281548110613180576131806152fc565b90600052602060002001549050808760000184815481106131a3576131a36152fc565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806131d6576131d66155fa565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610466565b6000915050610466565b805460288201546040516318b1771f60e01b8152600260048201526001600160a01b039182166024820152600092839283929116906318b1771f90604401602060405180830381865afa158015613276573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061329a91906155bd565b905060ff8160ff16036132b35750600093849350915050565b600184015460405163c8c7fe6b60e01b815260ff831660048201526000916001600160a01b03169063c8c7fe6b9060240161040060405180830381865afa158015613302573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613326919061566d565b6080810151909150600116600003613384576103c08101516029860154602c8701546001600160801b039092169450670de0b6b3a764000091613369908661540e565b6133739190615341565b61337d91906155d8565b93506134c0565b6001850154600d86015460405163c8c7fe6b60e01b815260ff90911660048201526000916001600160a01b03169063c8c7fe6b9060240161040060405180830381865afa1580156133d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fd919061566d565b6103e0810151600a880154600d890154604051636047675960e01b81526001600160a01b03610100909204821660048201526001600160801b0390931697509293506000921690636047675990602401602060405180830381865afa15801561346a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348e91906152ae565b6029880154602c89015491925082916134a7908861540e565b6134b19190615341565b6134bb91906155d8565b955050505b5050915091565b60008183106134d65781610463565b5090919050565b8454613507906001600160a01b03166134f68486615421565b6001600160a01b0387169190612f2a565b8454604051634086012960e11b8152600260048201526001600160a01b0386811660248301526044820186905260648201859052608482018490529091169063810c02529060a401600060405180830381600087803b15801561356957600080fd5b505af115801561357d573d6000803e3d6000fd5b505050505050505050565b60008160ff168360ff1611156135be576135a282846158ba565b6135ad90600a6159b7565b6135b790856155d8565b9050612e0a565b8160ff168360ff1610156135eb576135d683836158ba565b6135e190600a6159b7565b6135b79085615341565b5082612e0a565b6000613647826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136c49092919063ffffffff16565b8051909150156108435780806020019051810190613665919061513f565b6108435760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161034e565b6060611fa8848460008585600080866001600160a01b031685876040516136eb91906159c6565b60006040518083038185875af1925050503d8060008114613728576040519150601f19603f3d011682016040523d82523d6000602084013e61372d565b606091505b509150915061373e87838387613749565b979650505050505050565b606083156137b85782516000036137b1576001600160a01b0385163b6137b15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161034e565b5081611fa8565b611fa883838151156137cd5781518083602001fd5b8060405162461bcd60e51b815260040161034e91906159e2565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101919091526101808101613855613907565b905290565b6040518061022001604052806138916040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806101400160405280600a906020820280368337509192915050565b60006020828403121561393857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b03811182821017156139785761397861393f565b60405290565b604080519081016001600160401b03811182821017156139785761397861393f565b60405160e081016001600160401b03811182821017156139785761397861393f565b604051606081016001600160401b03811182821017156139785761397861393f565b60405161040081016001600160401b03811182821017156139785761397861393f565b604051601f8201601f191681016001600160401b0381118282101715613a2f57613a2f61393f565b604052919050565b60006001600160401b03821115613a5057613a5061393f565b5060051b60200190565b6001600160a01b03811681146103de57600080fd5b803561079d81613a5a565b600082601f830112613a8b57600080fd5b81356020613aa0613a9b83613a37565b613a07565b82815260059290921b84018101918181019086841115613abf57600080fd5b8286015b84811015613ae3578035613ad681613a5a565b8352918301918301613ac3565b509695505050505050565b60008060408385031215613b0157600080fd5b82356001600160401b0380821115613b1857600080fd5b613b2486838701613a7a565b93506020850135915080821115613b3a57600080fd5b50613b4785828601613a7a565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613b8957835183529284019291840191600101613b6d565b50909695505050505050565b80356008811061079d57600080fd5b80356003811061079d57600080fd5b60006101408284031215613bc657600080fd5b613bce613955565b9050613bd982613b95565b8152613be760208301613ba4565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e082015261010080830135818301525061012080830135818301525092915050565b80151581146103de57600080fd5b600060608284031215613c6657600080fd5b604051606081018181106001600160401b0382111715613c8857613c8861393f565b6040529050808235613c9981613c46565b81526020830135613ca981613c46565b60208201526040830135613cbc81613c46565b6040919091015292915050565b600082601f830112613cda57600080fd5b81356001600160401b03811115613cf357613cf361393f565b613d06601f8201601f1916602001613a07565b818152846020838601011115613d1b57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613d4957600080fd5b81356020613d59613a9b83613a37565b82815260059290921b84018101918181019086841115613d7857600080fd5b8286015b84811015613ae35780356001600160401b0380821115613d9c5760008081fd5b908801906040828b03601f1901811315613db65760008081fd5b613dbe61397e565b8784013583811115613dd05760008081fd5b613dde8d8a83880101613cc9565b825250908301359082821115613df45760008081fd5b613e028c8984870101613a7a565b818901528652505050918301918301613d7c565b60006040808385031215613e2957600080fd5b613e3161397e565b915082356001600160401b0380821115613e4a57600080fd5b818501915085601f830112613e5e57600080fd5b81356020613e6e613a9b83613a37565b82815260059290921b84018101918181019089841115613e8d57600080fd5b8286015b84811015613f0c57803586811115613ea95760008081fd5b8701808c03601f1901891315613ebf5760008081fd5b613ec761397e565b8582013588811115613ed95760008081fd5b613ee78e8883860101613cc9565b8252509089013590613ef882613a5a565b808601919091528352918301918301613e91565b5087525086810135945082851115613f2357600080fd5b613f2f88868901613d38565b81870152505050505092915050565b600082601f830112613f4f57600080fd5b81356020613f5f613a9b83613a37565b828152600592831b8501820192828201919087851115613f7e57600080fd5b8387015b858110156140735780356001600160401b0380821115613fa25760008081fd5b908901906040828c03601f1901811315613fbc5760008081fd5b613fc461397e565b8884013583811115613fd65760008081fd5b613fe48e8b83880101613cc9565b8252508184013583811115613ff95760008081fd5b8085019450508c603f85011261401157600092508283fd5b888401359250614023613a9b84613a37565b83815292861b8401820192898101908e8511156140405760008081fd5b948301945b8486101561405e5785358252948a0194908a0190614045565b828b0152508752505050928401928401613f82565b5090979650505050505050565b6000604080838503121561409357600080fd5b61409b61397e565b915082356001600160401b03808211156140b457600080fd5b818501915085601f8301126140c857600080fd5b813560206140d8613a9b83613a37565b82815260059290921b840181019181810190898411156140f757600080fd5b8286015b84811015614169578035868111156141135760008081fd5b8701808c03601f19018913156141295760008081fd5b61413161397e565b85820135888111156141435760008081fd5b6141518e8883860101613cc9565b825250908901358582015283529183019183016140fb565b508752508681013594508285111561418057600080fd5b613f2f88868901613f3e565b600082601f83011261419d57600080fd5b813560206141ad613a9b83613a37565b828152600592831b85018201928282019190878511156141cc57600080fd5b8387015b858110156140735780356001600160401b03808211156141f05760008081fd5b908901906040828c03601f190181131561420a5760008081fd5b61421261397e565b88840135838111156142245760008081fd5b6142328e8b83880101613cc9565b82525081840135838111156142475760008081fd5b8085019450508c603f85011261425f57600092508283fd5b888401359250614271613a9b84613a37565b83815292861b8401820192898101908e85111561428e5760008081fd5b948301945b848610156142ac5785358252948a0194908a0190614293565b828b01525087525050509284019284016141d0565b600060408083850312156142d457600080fd5b6142dc61397e565b915082356001600160401b03808211156142f557600080fd5b818501915085601f83011261430957600080fd5b81356020614319613a9b83613a37565b82815260059290921b8401810191818101908984111561433857600080fd5b8286015b848110156143aa578035868111156143545760008081fd5b8701808c03601f190189131561436a5760008081fd5b61437261397e565b85820135888111156143845760008081fd5b6143928e8883860101613cc9565b8252509089013585820152835291830191830161433c565b50875250868101359450828511156143c157600080fd5b613f2f8886890161418c565b600082601f8301126143de57600080fd5b813560206143ee613a9b83613a37565b828152600592831b850182019282820191908785111561440d57600080fd5b8387015b858110156140735780356001600160401b03808211156144315760008081fd5b908901906040828c03601f190181131561444b5760008081fd5b61445361397e565b88840135838111156144655760008081fd5b6144738e8b83880101613cc9565b82525081840135838111156144885760008081fd5b8085019450508c603f8501126144a057600092508283fd5b8884013592506144b2613a9b84613a37565b83815292861b8401820192898101908e8511156144cf5760008081fd5b948301945b848610156144f957853593506144e984613c46565b838252948a0194908a01906144d4565b828b0152508752505050928401928401614411565b6000604080838503121561452157600080fd5b61452961397e565b915082356001600160401b038082111561454257600080fd5b818501915085601f83011261455657600080fd5b81356020614566613a9b83613a37565b82815260059290921b8401810191818101908984111561458557600080fd5b8286015b84811015614604578035868111156145a15760008081fd5b8701808c03601f19018913156145b75760008081fd5b6145bf61397e565b85820135888111156145d15760008081fd5b6145df8e8883860101613cc9565b82525090890135906145f082613c46565b808601919091528352918301918301614589565b508752508681013594508285111561461b57600080fd5b613f2f888689016143cd565b6000604080838503121561463a57600080fd5b61464261397e565b915082356001600160401b038082111561465b57600080fd5b818501915085601f83011261466f57600080fd5b8135602061467f613a9b83613a37565b82815260059290921b8401810191818101908984111561469e57600080fd5b8286015b84811015614169578035868111156146ba5760008081fd5b8701808c03601f19018913156146d05760008081fd5b6146d861397e565b85820135888111156146ea5760008081fd5b6146f88e8883860101613cc9565b825250908901358582015283529183019183016146a2565b600082601f83011261472157600080fd5b81356020614731613a9b83613a37565b82815260059290921b8401810191818101908684111561475057600080fd5b8286015b84811015613ae3576001600160401b03808235111561477257600080fd5b813588016040818b03601f1901121561478a57600080fd5b61479261397e565b86820135838111156147a357600080fd5b6147b18c8983860101613cc9565b8252506040820135838111156147c657600080fd5b8083019250508a603f8301126147db57600080fd5b868201356147eb613a9b82613a37565b81815260059190911b830160400190888101908d83111561480b57600080fd5b604085015b8381101561484357868135111561482657600080fd5b6148368f60408335890101613cc9565b8352918a01918a01614810565b50838a0152505085525050918301918301614754565b6000604080838503121561486c57600080fd5b61487461397e565b915082356001600160401b038082111561488d57600080fd5b818501915085601f8301126148a157600080fd5b813560206148b1613a9b83613a37565b82815260059290921b840181019181810190898411156148d057600080fd5b8286015b84811015614960578035868111156148ec5760008081fd5b8701808c03601f19018913156149025760008081fd5b61490a61397e565b858201358881111561491c5760008081fd5b61492a8e8883860101613cc9565b825250898201358881111561493f5760008081fd5b61494d8e8883860101613cc9565b82880152508452509183019183016148d4565b508752508681013594508285111561497757600080fd5b613f2f88868901614710565b600060e0828403121561499557600080fd5b61499d6139a0565b905081356001600160401b03808211156149b657600080fd5b6149c285838601613e16565b835260208401359150808211156149d857600080fd5b6149e485838601614080565b602084015260408401359150808211156149fd57600080fd5b614a09858386016142c1565b60408401526060840135915080821115614a2257600080fd5b614a2e8583860161450e565b60608401526080840135915080821115614a4757600080fd5b614a5385838601614627565b608084015260a0840135915080821115614a6c57600080fd5b614a7885838601614859565b60a084015260c0840135915080821115614a9157600080fd5b50614a9e84828501614859565b60c08301525092915050565b600080600060608486031215614abf57600080fd5b8335925060208401356001600160401b0380821115614add57600080fd5b908501906101c08288031215614af257600080fd5b614afa6139c2565b823582811115614b0957600080fd5b830160e0818a031215614b1b57600080fd5b614b236139a0565b614b2c82613a6f565b8152614b3a60208301613a6f565b6020820152614b4b60408301613a6f565b6040820152614b5c60608301613a6f565b6060820152614b6d60808301613a6f565b6080820152614b7e60a08301613a6f565b60a082015260c082013584811115614b9557600080fd5b614ba18b828501613a7a565b60c083015250825250614bb78860208501613bb3565b6020820152614bca886101608501613c54565b6040820152809450506040860135915080821115614be757600080fd5b50614bf486828701614983565b9150509250925092565b600060208284031215614c1057600080fd5b8135612e0a81613a5a565b600060208284031215614c2d57600080fd5b81356001600160401b0380821115614c4457600080fd5b908301906101408286031215614c5957600080fd5b614c61613955565b823582811115614c7057600080fd5b614c7c87828601613cc9565b8252506020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100915081830135828201526101209150614ce2828401613b95565b91810191909152949350505050565b600060808284031215614d0357600080fd5b604051608081018181106001600160401b0382111715614d2557614d2561393f565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b600060808284031215614d6857600080fd5b6104638383614cf1565b602080825282518282018190526000919060409081850190868401855b82811015614dd557815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101614d8f565b5091979650505050505050565b60008060008060808587031215614df857600080fd5b5050823594602084013594506040840135936060013592509050565b8060005b600a811015610c82578151845260209384019390910190600101614e18565b81516001600160a01b031681526102c081016020830151614e6360208401826001600160a01b03169052565b506040830151614e7e60408401826001600160a01b03169052565b506060830151614e9960608401826001600160a01b03169052565b506080830151614eb460808401826001600160a01b03169052565b5060a0830151614ecf60a08401826001600160a01b03169052565b5060c0830151614ee360c084018215159052565b5060e083810151908301526101008084015190830152610120808401519083015261014080840151908301526101608084015115159083015261018080840151614f2f82850182614e14565b505092915050565b600080600060c08486031215614f4c57600080fd5b614f568585614cf1565b956080850135955060a0909401359392505050565b60008060008060008060c08789031215614f8457600080fd5b863595506020870135614f9681613a5a565b94506040870135614fa681613a5a565b93506060870135614fb681613a5a565b92506080870135614fc681613a5a565b915060a0870135614fd681613c46565b809150509295509295509295565b6020808252600b908201526a4c69717569646174696e6760a81b604082015260600190565b600081518084526020808501945080840160005b838110156150425781516001600160a01b03168752958201959082019060010161501d565b509495945050505050565b6060815260006150606060830186615009565b82810360208401526150728186615009565b91505060018060a01b0383166040830152949350505050565b6000602080838503121561509e57600080fd5b82516001600160401b038111156150b457600080fd5b8301601f810185136150c557600080fd5b80516150d3613a9b82613a37565b81815260059190911b820183019083810190878311156150f257600080fd5b928401925b8284101561373e578351825292840192908401906150f7565b60208082526015908201527424b73b30b634b221b0b6363130b1b5a9b2b73232b960591b604082015260600190565b60006020828403121561515157600080fd5b8151612e0a81613c46565b6020808252601390820152724f6e6c795472616465724f72466163746f727960681b604082015260600190565b60005b838110156151a457818101518382015260200161518c565b50506000910152565b600081518084526151c5816020860160208601615189565b601f01601f19169290920160200192915050565b634e487b7160e01b600052602160045260246000fd5b6008811061520d57634e487b7160e01b600052602160045260246000fd5b9052565b82815260406020820152600082516101408060408501526152366101808501836151ad565b91506020850151606085015260408501516080850152606085015160a0850152608085015160c085015260a085015160e085015260c0850151610100818187015260e08701519150610120828188015281880151848801528088015193505050506152a56101608501826151ef565b50949350505050565b6000602082840312156152c057600080fd5b5051919050565b82815260a08101612e0a6020830184805182526020810151602083015260408101516040830152606081015160608301525050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161533a5761533a615312565b5060010190565b808202811582820484141761046657610466615312565b84815260e0810161538d6020830186805182526020810151602083015260408101516040830152606081015160608301525050565b60a082019390935260c0015292915050565b805163ffffffff8116811461079d57600080fd5b600080604083850312156153c657600080fd5b6153cf8361539f565b91506153dd6020840161539f565b90509250929050565b805161079d81613a5a565b60006020828403121561540357600080fd5b8151612e0a81613a5a565b8181038181111561046657610466615312565b8082018082111561046657610466615312565b6001600160a01b038316815281516102a0820190615477906020840190805182526020810151602083015260408101516040830152606081015160608301525050565b602083015160a083810191909152604084015160c080850191909152606085015160e0808601919091526080860151610100808701919091529286015161012080870191909152918601516101408087019190915290860151610160808701919091529286015161018080870191909152918601516101a080870191909152908601516101c080870191909152928601516101e080870191909152918601516102008087019190915290860151610220860152918501516102408501528401516102608401529092015161028090910152919050565b6000806000806080858703121561556357600080fd5b845161556e81613a5a565b602086015190945061557f81613a5a565b604086015190935061559081613a5a565b60608601519092506155a181613a5a565b939692955090935050565b805160ff8116811461079d57600080fd5b6000602082840312156155cf57600080fd5b610463826155ac565b6000826155f557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fd5b805166ffffffffffffff8116811461079d57600080fd5b805162ffffff8116811461079d57600080fd5b80516bffffffffffffffffffffffff8116811461079d57600080fd5b80516001600160801b038116811461079d57600080fd5b6000610400828403121561568057600080fd5b6156886139e4565b82518152615698602084016153e6565b60208201526156a9604084016155ac565b60408201526156ba606084016155ac565b60608201526156cb60808401615610565b60808201526156dc60a08401615627565b60a08201526156ed60c0840161539f565b60c08201526156fe60e0840161539f565b60e082015261010061571181850161539f565b9082015261012061572384820161539f565b9082015261014061573584820161539f565b908201526101606157478482016153e6565b9082015261018061575984820161539f565b908201526101a061576b8482016155ac565b908201526101c061577d84820161539f565b908201526101e061578f84820161563a565b908201526102006157a1848201615656565b908201526102206157b384820161563a565b908201526102406157c584820161539f565b908201526102606157d784820161563a565b908201526102806157e984820161563a565b908201526102a06157fb84820161563a565b908201526102c061580d84820161563a565b908201526102e061581f84820161563a565b9082015261030061583184820161563a565b9082015261032061584384820161563a565b908201526103406158558482016153e6565b9082015261036061586784820161539f565b9082015261038061587984820161539f565b908201526103a061588b84820161539f565b908201526103c061589d848201615656565b908201526103e06158af848201615656565b908201529392505050565b60ff828116828216039081111561046657610466615312565b600181815b8085111561590e5781600019048211156158f4576158f4615312565b8085161561590157918102915b93841c93908002906158d8565b509250929050565b60008261592557506001610466565b8161593257506000610466565b816001811461594857600281146159525761596e565b6001915050610466565b60ff84111561596357615963615312565b50506001821b610466565b5060208310610133831016604e8410600b8410161715615991575081810a610466565b61599b83836158d3565b80600019048211156159af576159af615312565b029392505050565b600061046360ff841683615916565b600082516159d8818460208701615189565b9190910192915050565b60208152600061046360208301846151ad56fea26469706673582212204526fb43af494063f1ce74d140a34d693196d1f14b9be8b4ab8981b2c95d1a1064736f6c63430008110033
Deployed Bytecode
0x6080604052600436106101025760003560e01c80637489ec231161009557806390cdaaba1161006457806390cdaaba146102a15780639642a948146102c1578063b9091f22146102e3578063c74c54cf146102f6578063d219c26d1461031657600080fd5b80637489ec231461020f5780637c3506241461022f57806380bf219e146102515780638792e6211461028157600080fd5b80635102a708116100d15780635102a708146101a7578063573cdef4146101ba57806369e92224146101da578063715824e4146101fa57600080fd5b806325e4ac2b1461010e57806328bc2fca14610130578063299887dc1461015957806332f289cf1461017957600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012e610129366004613926565b61032b565b005b61014361013e366004613aee565b6103e1565b6040516101509190613b51565b60405180910390f35b34801561016557600080fd5b5061012e610174366004614aaa565b61046c565b34801561018557600080fd5b50610199610194366004614bfe565b61065d565b604051908152602001610150565b6101996101b5366004614c1b565b610669565b3480156101c657600080fd5b506101996101d5366004614d56565b6107a2565b3480156101e657600080fd5b5061012e6101f5366004614aaa565b61081f565b34801561020657600080fd5b50610199610848565b34801561021b57600080fd5b5061012e61022a366004613926565b610859565b34801561023b57600080fd5b506102446108f1565b6040516101509190614d72565b34801561025d57600080fd5b5061027161026c366004614d56565b610a6b565b6040519015158152602001610150565b34801561028d57600080fd5b5061012e61029c366004614de2565b610ba0565b3480156102ad57600080fd5b5061012e6102bc366004614aaa565b610c88565b3480156102cd57600080fd5b506102d6610da0565b6040516101509190614e37565b61012e6102f1366004614f37565b610e7b565b34801561030257600080fd5b5061012e610311366004614f6b565b610fcd565b34801561032257600080fd5b50600254610199565b602d5460ff16156103575760405162461bcd60e51b815260040161034e90614fe4565b60405180910390fd5b61035f611274565b61036960006112cd565b60405163660851a560e01b8152600060048201526024810182905273426ded3b3dc4971951d900e50b79564c3601f88d9063660851a5906044015b60006040518083038186803b1580156103bc57600080fd5b505af41580156103d0573d6000803e3d6000fd5b505050506103de600160a055565b50565b60055460235460405163c41b1ab360e01b81526060926001600160a01b039081169263c41b1ab39261041c928892889291169060040161504d565b6000604051808303816000875af115801561043b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610463919081019061508b565b90505b92915050565b6104746113d6565b6104905760405162461bcd60e51b815260040161034e90615110565b602954602a54602b54602c5460405163066659ff60e41b8152600060048201526024810188905273426ded3b3dc4971951d900e50b79564c3601f88d906366659ff090604401602060405180830381865af41580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610517919061513f565b156105555760405162461bcd60e51b815260206004820152600e60248201526d13dc99195c939bdd119a5b1b195960921b604482015260640161034e565b60006105618189611599565b805190915061059b576029541561059157600061057e6000611687565b905061058b60008261184e565b5061059b565b61059b6000611cc7565b6105a56000611e01565b50600b54602354602954602a54602b54602c546040516318a363dd60e11b81526001600160a01b039586166004820152602481018f9052604481018c9052606481018b9052608481018a905260a4810189905260c481019490945260e4840192909252610104830152610124820152911690633146c7ba9061014401600060405180830381600087803b15801561063b57600080fd5b505af115801561064f573d6000803e3d6000fd5b505050505050505050505050565b60006104668183611e4e565b6000610673611fb0565b61068f5760405162461bcd60e51b815260040161034e9061515c565b602d5460ff16156106b25760405162461bcd60e51b815260040161034e90614fe4565b6106ba611274565b6106c460006112cd565b6106d2826101200151611fe7565b15610759576040516353c151d160e01b815273426ded3b3dc4971951d900e50b79564c3601f88d906353c151d190610711906000908690600401615211565b602060405180830381865af415801561072e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075291906152ae565b9050610793565b60405163f774b64960e01b815273426ded3b3dc4971951d900e50b79564c3601f88d9063f774b64990610711906000908690600401615211565b61079d600160a055565b919050565b604051631c6abf2360e21b815260009073426ded3b3dc4971951d900e50b79564c3601f88d906371aafc8c906107de90849086906004016152c7565b602060405180830381865af41580156107fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046691906152ae565b6108276113d6565b6108435760405162461bcd60e51b815260040161034e90615110565b505050565b60006108546000611e01565b905090565b610861611fb0565b61087d5760405162461bcd60e51b815260040161034e9061515c565b602d5460ff16156108a05760405162461bcd60e51b815260040161034e90614fe4565b6108a8611274565b6108b260006112cd565b604051638e3f043560e01b8152600060048201526024810182905273426ded3b3dc4971951d900e50b79564c3601f88d90638e3f0435906044016103a4565b606060006108ff603961201f565b90508060000361090d575090565b806001600160401b038111156109255761092561393f565b60405190808252806020026020018201604052801561097e57816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282526000199092019101816109435790505b50915060005b81811015610a66576000610999603983612029565b600081815260386020908152604091829020825160a08082018552825460ff8116151583526001600160401b03610100909104811683860190815260018501548488019081526002860154606080870191909152600390960154608080870191825289519586018a528a86529051978501979097529051909116958201959095529351918401919091528051151591830191909152865192935091869085908110610a4657610a466152fc565b602002602001018190525050508080610a5e90615328565b915050610984565b505090565b6009546007546002546040516323e967a560e01b81526001600160a01b0392831660048201526024810191909152600092839216906323e967a590604401602060405180830381865afa158015610ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aea91906152ae565b905080600003610afd5750600092915050565b601854610b1d90600160401b900463ffffffff166509184e72a000615341565b604051631c6abf2360e21b815273426ded3b3dc4971951d900e50b79564c3601f88d906371aafc8c90610b579060009088906004016152c7565b602060405180830381865af4158015610b74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9891906152ae565b109392505050565b610ba8611fb0565b610bc45760405162461bcd60e51b815260040161034e9061515c565b602d5460ff1615610be75760405162461bcd60e51b815260040161034e90614fe4565b610bef611274565b610bf960006112cd565b60405163069dae5d60e01b8152600060048201526024810185905260448101849052606481018390526084810182905273426ded3b3dc4971951d900e50b79564c3601f88d9063069dae5d9060a40160006040518083038186803b158015610c6057600080fd5b505af4158015610c74573d6000803e3d6000fd5b50505050610c82600160a055565b50505050565b610c906113d6565b610cac5760405162461bcd60e51b815260040161034e90615110565b602954602a54602b54602c5460405163066659ff60e41b8152600060048201526024810188905273426ded3b3dc4971951d900e50b79564c3601f88d906366659ff090604401602060405180830381865af4158015610d0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d33919061513f565b15610d745760405162461bcd60e51b815260206004820152601160248201527013dc99195c939bdd10d85b98d95b1b1959607a1b604482015260640161034e565b6000610d808189611599565b80519091501561059b576060810151608082015161059b91600091612035565b610da86137e7565b604080516101a081018252602380546001600160a01b03908116835260245481166020840152602554811683850152602654811660608401526027548116608084015260285490811660a0840152600160a01b900460ff908116151560c084015260295460e0840152602a54610100840152602b54610120840152602c5461014080850191909152602d54909116151561016084015283519081019384905291929091610180840191602e90600a9082845b815481526020019060010190808311610e5a57505050505081525050905090565b6000546040516335d2155560e11b81523360048201526001600160a01b0390911690636ba42aaa90602401602060405180830381865afa158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee7919061513f565b610f205760405162461bcd60e51b815260206004820152600a60248201526937b7363ca5b2b2b832b960b11b604482015260640161034e565b602d5460ff1615610f435760405162461bcd60e51b815260040161034e90614fe4565b610f4b611274565b610f5560006112cd565b604051630762b6ed60e21b815273426ded3b3dc4971951d900e50b79564c3601f88d90631d8adbb490610f9390600090879087908790600401615358565b60006040518083038186803b158015610fab57600080fd5b505af4158015610fbf573d6000803e3d6000fd5b50505050610843600160a055565b609f54610100900460ff1615808015610fed5750609f54600160ff909116105b806110075750303b1580156110075750609f5460ff166001145b61106a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161034e565b609f805460ff19166001179055801561108d57609f805461ff0019166101001790555b6001600160a01b037f000000000000000000000000e1b50bba2255bbc60e4d4cdb4c77df61d1fddd8d1630036110c257600080fd5b6001600160a01b03861661110f5760405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a59131a5c5d5a591a5d1e541bdbdb60621b604482015260640161034e565b600287146111505760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59141c9bda9958dd60921b604482015260640161034e565b600080546001600160a01b03199081163317909155600180546001600160a01b038981169190931617905560408051306020820152858316918101919091529085166060820152821515608082015260a00160408051601f19818403018152919052805160209091012060025560288054831515600160a01b0260ff60a01b19909116179055602480546001600160a01b038086166001600160a01b031992831617909255602380549288169290911691909117905561121060006112cd565b61121b60008561213b565b6112256000612410565b801561126b57609f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b600260a054036112c65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161034e565b600260a055565b60248181015482546040516370693e1560e11b8152600260048201526001600160a01b039283169381018490526000928392169063e0d27c2a906044016040805180830381865afa158015611326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134a91906153b3565b6003860154919350915063ffffffff808416911610156113855761136d8461247b565b60038401805463ffffffff191663ffffffff84161790555b600384015463ffffffff808316640100000000909204161015610c82576113ac8484612771565b60038401805463ffffffff83166401000000000267ffffffff000000001990911617905550505050565b600080546040516335d2155560e11b81523360048201526001600160a01b0390911690636ba42aaa90602401602060405180830381865afa15801561141f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611443919061513f565b1561144e5750600190565b600754604080516312929ec160e21b815290516000926001600160a01b031691634a4a7b049160048281019260209291908290030181865afa158015611498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bc91906153f1565b9050806001600160a01b031663ac4ab3fb336040516020016114fc906020808252600a908201526921a7a72a2927a62622a960b11b604082015260600190565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b81526004016115439291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015611560573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611584919061513f565b1561159157600191505090565b600091505090565b6115d66040518060a0016040528060001515815260200160006001600160401b031681526020016000815260200160008152602001600081525090565b5060008181526038830160208181526040808420815160a081018352815460ff8116151582526001600160401b0361010082041682860152600183018054948301949094526002830180546060840152600384018054608085018190528a8a529790965268ffffffffffffffffff19909116909255918590558490559290556116626039850184612979565b508084602301600701600082825461167a919061540e565b9091555091949350505050565b6116b26040518060800160405280600081526020016000815260200160008152602001600081525090565b600a8201546025830154604051636047675960e01b81526001600160a01b0391821660048201529116908190636047675990602401602060405180830381865afa158015611704573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172891906152ae565b60208301526026830154604051636047675960e01b81526001600160a01b03918216600482015290821690636047675990602401602060405180830381865afa158015611779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179d91906152ae565b60408381019190915260278401549051636047675960e01b81526001600160a01b03918216600482015290821690636047675990602401602060405180830381865afa1580156117f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181591906152ae565b6060830152602683015460288401546001600160a01b03908116911614611840578160600151611846565b81604001515b825250919050565b61185661385a565b60288301546001600160a01b03167382af49447d8a07e3bd95bd0d56f35241523fbab019016118e8577382af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b1580156118ce57600080fd5b505af11580156118e2573d6000803e3d6000fd5b50505050505b6009830154600784015460028501546040516323e967a560e01b81526001600160a01b039283166004820152602481019190915260009291909116906323e967a590604401602060405180830381865afa15801561194a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196e91906152ae565b838352905061197c84612985565b608083015260288401546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156119cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ef91906152ae565b60208301528015611aaa578151604051631ed6ab2960e11b815273426ded3b3dc4971951d900e50b79564c3601f88d91633dad565291611a389188916000908190600401615358565b602060405180830381865af4158015611a55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a79919061513f565b15611aa55760208201516101c083018190526028850154611aa59186916001600160a01b0316906129c0565b611c55565b602a8401546029850154611abe919061540e565b606083018190526018850154611ade919063ffffffff90811690612aaf16565b60a0830152602d84015460ff1615611b1a5760188401546060830151611b149163ffffffff600160601b909104811690612aaf16565b60c08301525b60c0820151602b85015460a0840151611b339190615421565b611b3d9190615421565b60e0830152611b4c8483612acf565b91506000611b5985612bb2565b6040516370a0823160e01b81523060048201529091506001600160a01b038216906370a0823190602401602060405180830381865afa158015611ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc491906152ae565b6040840152610180830151151580611be157506000836101a00151115b15611bf857611bf1858483612bf3565b9250611c04565b60408301516101e08401525b602a85015460298601556000602b86015560288501546101c0840151611c379187916001600160a01b03909116906129c0565b611c478582856101e001516129c0565b50602d8401805460ff191690555b600b8401546023850154604051631bed973760e01b81526001600160a01b0392831692631bed973792611c8f929116908690600401615434565b600060405180830381600087803b158015611ca957600080fd5b505af1158015611cbd573d6000803e3d6000fd5b5050505050505050565b60288101546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611d12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3691906152ae565b6028830154909150611d539083906001600160a01b0316836129c0565b6000611d5e83612bb2565b60288401549091506001600160a01b03808316911614611df2576040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de391906152ae565b9050611df08483836129c0565b505b5050602d01805460ff19169055565b60288101546000906001600160a01b03167382af49447d8a07e3bd95bd0d56f35241523fbab114611e465760238201544790610466906001600160a01b031682612e11565b506000919050565b6009820154600783015460028401546040516323e967a560e01b81526001600160a01b0392831660048201526024810191909152600092839216906323e967a590604401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed391906152ae565b905080158015611ee557506029840154155b611f1e5760405162461bcd60e51b815260206004820152600a602482015269139bdd105b1b1bddd95960b21b604482015260640161034e565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8991906152ae565b6023860154909150611fa8906001600160a01b03868116911683612f2a565b949350505050565b600080546001600160a01b03163303611fc95750600190565b6023546001600160a01b03163303611fe15750600190565b50600090565b60006002826007811115611ffd57611ffd6151d9565b148061046657506003826007811115612018576120186151d9565b1492915050565b6000610466825490565b60006104638383612f7c565b61203d61385a565b61204684612985565b608082015260288401546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b991906152ae565b602082018190528311156121025760405162461bcd60e51b815260206004820152601060248201526f4e6f74456e6f75676842616c616e636560801b604482015260640161034e565b61210d848385612fa6565b6101208401526101008301526101c082018190526028850154610c829186916001600160a01b0316906129c0565b6009820154600783015460248085015460405163036226ff60e11b81526001600160a01b03938416600482015290831691810191909152600092839283929116906306c44dfe90604401608060405180830381865afa1580156121a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c6919061554d565b6025890180546001600160a01b038086166001600160a01b03199283161790925560268b01805483861690831617905560278b01805483851690831617905560288b018054928b1692909116821790556040805163313ce56760e01b81529051949850929650909450925063313ce5679160048281019260209291908290030181865afa15801561225b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227f91906155bd565b85600301600a6101000a81548160ff021916908360ff160217905550816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fd91906155bd565b8560030160096101000a81548160ff021916908360ff160217905550806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237b91906155bd565b60038601805460ff92909216600160401b0268ff00000000000000001990921691909117905560268501546001600160a01b03858116911614806123ce575060278501546001600160a01b038581169116145b6124095760405162461bcd60e51b815260206004820152600c60248201526b24b73b30b634b22a37b5b2b760a11b604482015260640161034e565b5050505050565b600581015460248083015460405163039fd84f60e11b81526001600160a01b03918216600482015230928101929092529091169063073fb09e90604401600060405180830381600087803b15801561246757600080fd5b505af1158015612409573d6000803e3d6000fd5b8054604051638947175b60e01b8152600260048201526000916001600160a01b031690638947175b90602401600060405180830381865afa1580156124c4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124ec919081019061508b565b9050600c815110156125315760405162461bcd60e51b815260206004820152600e60248201526d4d697373696e67436f6e6669677360901b604482015260640161034e565b6125568160005b81518110612548576125486152fc565b602002602001015160601c90565b6004830180546001600160a01b0319166001600160a01b0392909216919091179055612583816001612538565b6005830180546001600160a01b0319166001600160a01b03929092169190911790556125b0816002612538565b6006830180546001600160a01b0319166001600160a01b03929092169190911790556125dd816003612538565b6007830180546001600160a01b0319166001600160a01b039290921691909117905561260a816004612538565b6008830180546001600160a01b0319166001600160a01b0392909216919091179055612637816005612538565b6009830180546001600160a01b0319166001600160a01b0392909216919091179055612664816006612538565b600a830180546001600160a01b0319166001600160a01b0392909216919091179055612691816007612538565b600b830180546001600160a01b0319166001600160a01b03929092169190911790556126d4816008815181106126c9576126c96152fc565b602002602001015190565b600c8301556126fd8160095b815181106126f0576126f06152fc565b60200260200101516130ac565b600d8301805460ff191660ff9290921691909117905561271e81600a612538565b600d830180546001600160a01b039290921661010002610100600160a81b031990921691909117905580600b8151811061275a5761275a6152fc565b602002602001015182600401600a01819055505050565b8154604051633e65196f60e01b8152600260048201526001600160a01b0383811660248301526000921690633e65196f90604401600060405180830381865afa1580156127c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127ea919081019061508b565b905060078151101561282f5760405162461bcd60e51b815260206004820152600e60248201526d4d697373696e67436f6e6669677360901b604482015260640161034e565b6128538160005b81518110612846576128466152fc565b60200260200101516130e9565b60188401805463ffffffff191663ffffffff9290921691909117905561287a816001612836565b60188401805463ffffffff929092166401000000000267ffffffff00000000199092169190911790556128ae816002612836565b60188401805463ffffffff92909216600160401b026bffffffff0000000000000000199092169190911790556128e5816003612836565b60188401805463ffffffff92909216600160601b0263ffffffff60601b199092169190911790556129178160056126e0565b60188401805460ff92909216600160a01b0260ff60a01b1990921691909117905560008160068151811061294d5761294d6152fc565b6020026020010151118360180160000160156101000a81548160ff021916908315150217905550505050565b60006104638383613128565b60008060006129938461321b565b91509150818460230160080160008282546129ae9190615421565b9091555050602c909301929092555090565b806000036129cd57505050565b7382af49447d8a07e3bd95bd0d56f35241523fbab0196001600160a01b03831601612a9357604051632e1a7d4d60e01b8152600481018290527382af49447d8a07e3bd95bd0d56f35241523fbab190632e1a7d4d90602401600060405180830381600087803b158015612a3f57600080fd5b505af1158015612a53573d6000803e3d6000fd5b50505060238401546040516001600160a01b03909116915082156108fc029083906000818181858888f19350505050158015610c82573d6000803e3d6000fd5b6023830154610843906001600160a01b03848116911683612f2a565b6000620186a0612ac563ffffffff841685615341565b61046391906155d8565b612ad761385a565b60208201516101c083018190526060830151612af2916134c7565b61010083018190526101c083018051612b0c90839061540e565b9052506101c082015115612b4c5760e08201516101c0830151612b2e916134c7565b61012083018190526101c083018051612b4890839061540e565b9052505b8161010001518260600151612b61919061540e565b61018083015261012082015160e0830151612b7c919061540e565b6101a08301526028830154610100830151610120840151612bac9286926001600160a01b039091169160006134dd565b50919050565b602681015460288201546000916001600160a01b03908116911603612be25750602701546001600160a01b031690565b50602601546001600160a01b031690565b612bfb61385a565b8260400151600003612c0e575081612e0a565b82515160268501546000906001600160a01b03858116911614612c3657845160600151612c3d565b8451604001515b9050600086600301600a9054906101000a900460ff1690506000856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb991906155bd565b90506000612ce5838386888c6101800151612cd49190615341565b612cde91906155d8565b9190613588565b6040890151909150612cf790826134c7565b61014089018190526040890151612d0e919061540e565b6101e0890181905215612d66576000612d34848487898d6101a00151612cd49190615341565b6101e08a0151909150612d4790826134c7565b6101608a018190526101e08a018051612d6190839061540e565b905250505b61014088015185908590612d7b908587613588565b612d859190615341565b612d8f91906155d8565b8861018001818151612da1919061540e565b90525061016088015185908590612db9908587613588565b612dc39190615341565b612dcd91906155d8565b886101a001818151612ddf919061540e565b9052506101408801516101608901516101808a0151612e01928c928b926134dd565b87955050505050505b9392505050565b80471015612e615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161034e565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612eae576040519150601f19603f3d011682016040523d82523d6000602084013e612eb3565b606091505b50509050806108435760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161034e565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526108439084906135f2565b6000826000018281548110612f9357612f936152fc565b9060005260206000200154905092915050565b8060008084156130a3576029860154612fbf90866134c7565b9150818410156130075760405162461bcd60e51b8152602060048201526013602482015272496e73756666696369656e7442616c616e636560681b604482015260640161034e565b8186602301600601600082825461301e919061540e565b9091555061302e9050828461540e565b601887015490935061304b90839063ffffffff90811690612aaf16565b90508083106130655761305e818461540e565b9250613086565b8086602301600801600082825461307c9190615421565b9091555060009150505b60288601546130a39087906001600160a01b0316848460006134dd565b93509350939050565b600060ff8211156130e55760405162461bcd60e51b815260206004820152600360248201526209eaa760eb1b604482015260640161034e565b5090565b600063ffffffff8211156130e55760405162461bcd60e51b815260040161034e9060208082526004908201526327aa999960e11b604082015260600190565b6000818152600183016020526040812054801561321157600061314c60018361540e565b85549091506000906131609060019061540e565b90508181146131c5576000866000018281548110613180576131806152fc565b90600052602060002001549050808760000184815481106131a3576131a36152fc565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806131d6576131d66155fa565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610466565b6000915050610466565b805460288201546040516318b1771f60e01b8152600260048201526001600160a01b039182166024820152600092839283929116906318b1771f90604401602060405180830381865afa158015613276573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061329a91906155bd565b905060ff8160ff16036132b35750600093849350915050565b600184015460405163c8c7fe6b60e01b815260ff831660048201526000916001600160a01b03169063c8c7fe6b9060240161040060405180830381865afa158015613302573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613326919061566d565b6080810151909150600116600003613384576103c08101516029860154602c8701546001600160801b039092169450670de0b6b3a764000091613369908661540e565b6133739190615341565b61337d91906155d8565b93506134c0565b6001850154600d86015460405163c8c7fe6b60e01b815260ff90911660048201526000916001600160a01b03169063c8c7fe6b9060240161040060405180830381865afa1580156133d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fd919061566d565b6103e0810151600a880154600d890154604051636047675960e01b81526001600160a01b03610100909204821660048201526001600160801b0390931697509293506000921690636047675990602401602060405180830381865afa15801561346a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348e91906152ae565b6029880154602c89015491925082916134a7908861540e565b6134b19190615341565b6134bb91906155d8565b955050505b5050915091565b60008183106134d65781610463565b5090919050565b8454613507906001600160a01b03166134f68486615421565b6001600160a01b0387169190612f2a565b8454604051634086012960e11b8152600260048201526001600160a01b0386811660248301526044820186905260648201859052608482018490529091169063810c02529060a401600060405180830381600087803b15801561356957600080fd5b505af115801561357d573d6000803e3d6000fd5b505050505050505050565b60008160ff168360ff1611156135be576135a282846158ba565b6135ad90600a6159b7565b6135b790856155d8565b9050612e0a565b8160ff168360ff1610156135eb576135d683836158ba565b6135e190600a6159b7565b6135b79085615341565b5082612e0a565b6000613647826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136c49092919063ffffffff16565b8051909150156108435780806020019051810190613665919061513f565b6108435760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161034e565b6060611fa8848460008585600080866001600160a01b031685876040516136eb91906159c6565b60006040518083038185875af1925050503d8060008114613728576040519150601f19603f3d011682016040523d82523d6000602084013e61372d565b606091505b509150915061373e87838387613749565b979650505050505050565b606083156137b85782516000036137b1576001600160a01b0385163b6137b15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161034e565b5081611fa8565b611fa883838151156137cd5781518083602001fd5b8060405162461bcd60e51b815260040161034e91906159e2565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101919091526101808101613855613907565b905290565b6040518061022001604052806138916040518060800160405280600081526020016000815260200160008152602001600081525090565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806101400160405280600a906020820280368337509192915050565b60006020828403121561393857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b03811182821017156139785761397861393f565b60405290565b604080519081016001600160401b03811182821017156139785761397861393f565b60405160e081016001600160401b03811182821017156139785761397861393f565b604051606081016001600160401b03811182821017156139785761397861393f565b60405161040081016001600160401b03811182821017156139785761397861393f565b604051601f8201601f191681016001600160401b0381118282101715613a2f57613a2f61393f565b604052919050565b60006001600160401b03821115613a5057613a5061393f565b5060051b60200190565b6001600160a01b03811681146103de57600080fd5b803561079d81613a5a565b600082601f830112613a8b57600080fd5b81356020613aa0613a9b83613a37565b613a07565b82815260059290921b84018101918181019086841115613abf57600080fd5b8286015b84811015613ae3578035613ad681613a5a565b8352918301918301613ac3565b509695505050505050565b60008060408385031215613b0157600080fd5b82356001600160401b0380821115613b1857600080fd5b613b2486838701613a7a565b93506020850135915080821115613b3a57600080fd5b50613b4785828601613a7a565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613b8957835183529284019291840191600101613b6d565b50909695505050505050565b80356008811061079d57600080fd5b80356003811061079d57600080fd5b60006101408284031215613bc657600080fd5b613bce613955565b9050613bd982613b95565b8152613be760208301613ba4565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e082015261010080830135818301525061012080830135818301525092915050565b80151581146103de57600080fd5b600060608284031215613c6657600080fd5b604051606081018181106001600160401b0382111715613c8857613c8861393f565b6040529050808235613c9981613c46565b81526020830135613ca981613c46565b60208201526040830135613cbc81613c46565b6040919091015292915050565b600082601f830112613cda57600080fd5b81356001600160401b03811115613cf357613cf361393f565b613d06601f8201601f1916602001613a07565b818152846020838601011115613d1b57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613d4957600080fd5b81356020613d59613a9b83613a37565b82815260059290921b84018101918181019086841115613d7857600080fd5b8286015b84811015613ae35780356001600160401b0380821115613d9c5760008081fd5b908801906040828b03601f1901811315613db65760008081fd5b613dbe61397e565b8784013583811115613dd05760008081fd5b613dde8d8a83880101613cc9565b825250908301359082821115613df45760008081fd5b613e028c8984870101613a7a565b818901528652505050918301918301613d7c565b60006040808385031215613e2957600080fd5b613e3161397e565b915082356001600160401b0380821115613e4a57600080fd5b818501915085601f830112613e5e57600080fd5b81356020613e6e613a9b83613a37565b82815260059290921b84018101918181019089841115613e8d57600080fd5b8286015b84811015613f0c57803586811115613ea95760008081fd5b8701808c03601f1901891315613ebf5760008081fd5b613ec761397e565b8582013588811115613ed95760008081fd5b613ee78e8883860101613cc9565b8252509089013590613ef882613a5a565b808601919091528352918301918301613e91565b5087525086810135945082851115613f2357600080fd5b613f2f88868901613d38565b81870152505050505092915050565b600082601f830112613f4f57600080fd5b81356020613f5f613a9b83613a37565b828152600592831b8501820192828201919087851115613f7e57600080fd5b8387015b858110156140735780356001600160401b0380821115613fa25760008081fd5b908901906040828c03601f1901811315613fbc5760008081fd5b613fc461397e565b8884013583811115613fd65760008081fd5b613fe48e8b83880101613cc9565b8252508184013583811115613ff95760008081fd5b8085019450508c603f85011261401157600092508283fd5b888401359250614023613a9b84613a37565b83815292861b8401820192898101908e8511156140405760008081fd5b948301945b8486101561405e5785358252948a0194908a0190614045565b828b0152508752505050928401928401613f82565b5090979650505050505050565b6000604080838503121561409357600080fd5b61409b61397e565b915082356001600160401b03808211156140b457600080fd5b818501915085601f8301126140c857600080fd5b813560206140d8613a9b83613a37565b82815260059290921b840181019181810190898411156140f757600080fd5b8286015b84811015614169578035868111156141135760008081fd5b8701808c03601f19018913156141295760008081fd5b61413161397e565b85820135888111156141435760008081fd5b6141518e8883860101613cc9565b825250908901358582015283529183019183016140fb565b508752508681013594508285111561418057600080fd5b613f2f88868901613f3e565b600082601f83011261419d57600080fd5b813560206141ad613a9b83613a37565b828152600592831b85018201928282019190878511156141cc57600080fd5b8387015b858110156140735780356001600160401b03808211156141f05760008081fd5b908901906040828c03601f190181131561420a5760008081fd5b61421261397e565b88840135838111156142245760008081fd5b6142328e8b83880101613cc9565b82525081840135838111156142475760008081fd5b8085019450508c603f85011261425f57600092508283fd5b888401359250614271613a9b84613a37565b83815292861b8401820192898101908e85111561428e5760008081fd5b948301945b848610156142ac5785358252948a0194908a0190614293565b828b01525087525050509284019284016141d0565b600060408083850312156142d457600080fd5b6142dc61397e565b915082356001600160401b03808211156142f557600080fd5b818501915085601f83011261430957600080fd5b81356020614319613a9b83613a37565b82815260059290921b8401810191818101908984111561433857600080fd5b8286015b848110156143aa578035868111156143545760008081fd5b8701808c03601f190189131561436a5760008081fd5b61437261397e565b85820135888111156143845760008081fd5b6143928e8883860101613cc9565b8252509089013585820152835291830191830161433c565b50875250868101359450828511156143c157600080fd5b613f2f8886890161418c565b600082601f8301126143de57600080fd5b813560206143ee613a9b83613a37565b828152600592831b850182019282820191908785111561440d57600080fd5b8387015b858110156140735780356001600160401b03808211156144315760008081fd5b908901906040828c03601f190181131561444b5760008081fd5b61445361397e565b88840135838111156144655760008081fd5b6144738e8b83880101613cc9565b82525081840135838111156144885760008081fd5b8085019450508c603f8501126144a057600092508283fd5b8884013592506144b2613a9b84613a37565b83815292861b8401820192898101908e8511156144cf5760008081fd5b948301945b848610156144f957853593506144e984613c46565b838252948a0194908a01906144d4565b828b0152508752505050928401928401614411565b6000604080838503121561452157600080fd5b61452961397e565b915082356001600160401b038082111561454257600080fd5b818501915085601f83011261455657600080fd5b81356020614566613a9b83613a37565b82815260059290921b8401810191818101908984111561458557600080fd5b8286015b84811015614604578035868111156145a15760008081fd5b8701808c03601f19018913156145b75760008081fd5b6145bf61397e565b85820135888111156145d15760008081fd5b6145df8e8883860101613cc9565b82525090890135906145f082613c46565b808601919091528352918301918301614589565b508752508681013594508285111561461b57600080fd5b613f2f888689016143cd565b6000604080838503121561463a57600080fd5b61464261397e565b915082356001600160401b038082111561465b57600080fd5b818501915085601f83011261466f57600080fd5b8135602061467f613a9b83613a37565b82815260059290921b8401810191818101908984111561469e57600080fd5b8286015b84811015614169578035868111156146ba5760008081fd5b8701808c03601f19018913156146d05760008081fd5b6146d861397e565b85820135888111156146ea5760008081fd5b6146f88e8883860101613cc9565b825250908901358582015283529183019183016146a2565b600082601f83011261472157600080fd5b81356020614731613a9b83613a37565b82815260059290921b8401810191818101908684111561475057600080fd5b8286015b84811015613ae3576001600160401b03808235111561477257600080fd5b813588016040818b03601f1901121561478a57600080fd5b61479261397e565b86820135838111156147a357600080fd5b6147b18c8983860101613cc9565b8252506040820135838111156147c657600080fd5b8083019250508a603f8301126147db57600080fd5b868201356147eb613a9b82613a37565b81815260059190911b830160400190888101908d83111561480b57600080fd5b604085015b8381101561484357868135111561482657600080fd5b6148368f60408335890101613cc9565b8352918a01918a01614810565b50838a0152505085525050918301918301614754565b6000604080838503121561486c57600080fd5b61487461397e565b915082356001600160401b038082111561488d57600080fd5b818501915085601f8301126148a157600080fd5b813560206148b1613a9b83613a37565b82815260059290921b840181019181810190898411156148d057600080fd5b8286015b84811015614960578035868111156148ec5760008081fd5b8701808c03601f19018913156149025760008081fd5b61490a61397e565b858201358881111561491c5760008081fd5b61492a8e8883860101613cc9565b825250898201358881111561493f5760008081fd5b61494d8e8883860101613cc9565b82880152508452509183019183016148d4565b508752508681013594508285111561497757600080fd5b613f2f88868901614710565b600060e0828403121561499557600080fd5b61499d6139a0565b905081356001600160401b03808211156149b657600080fd5b6149c285838601613e16565b835260208401359150808211156149d857600080fd5b6149e485838601614080565b602084015260408401359150808211156149fd57600080fd5b614a09858386016142c1565b60408401526060840135915080821115614a2257600080fd5b614a2e8583860161450e565b60608401526080840135915080821115614a4757600080fd5b614a5385838601614627565b608084015260a0840135915080821115614a6c57600080fd5b614a7885838601614859565b60a084015260c0840135915080821115614a9157600080fd5b50614a9e84828501614859565b60c08301525092915050565b600080600060608486031215614abf57600080fd5b8335925060208401356001600160401b0380821115614add57600080fd5b908501906101c08288031215614af257600080fd5b614afa6139c2565b823582811115614b0957600080fd5b830160e0818a031215614b1b57600080fd5b614b236139a0565b614b2c82613a6f565b8152614b3a60208301613a6f565b6020820152614b4b60408301613a6f565b6040820152614b5c60608301613a6f565b6060820152614b6d60808301613a6f565b6080820152614b7e60a08301613a6f565b60a082015260c082013584811115614b9557600080fd5b614ba18b828501613a7a565b60c083015250825250614bb78860208501613bb3565b6020820152614bca886101608501613c54565b6040820152809450506040860135915080821115614be757600080fd5b50614bf486828701614983565b9150509250925092565b600060208284031215614c1057600080fd5b8135612e0a81613a5a565b600060208284031215614c2d57600080fd5b81356001600160401b0380821115614c4457600080fd5b908301906101408286031215614c5957600080fd5b614c61613955565b823582811115614c7057600080fd5b614c7c87828601613cc9565b8252506020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100915081830135828201526101209150614ce2828401613b95565b91810191909152949350505050565b600060808284031215614d0357600080fd5b604051608081018181106001600160401b0382111715614d2557614d2561393f565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b600060808284031215614d6857600080fd5b6104638383614cf1565b602080825282518282018190526000919060409081850190868401855b82811015614dd557815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101614d8f565b5091979650505050505050565b60008060008060808587031215614df857600080fd5b5050823594602084013594506040840135936060013592509050565b8060005b600a811015610c82578151845260209384019390910190600101614e18565b81516001600160a01b031681526102c081016020830151614e6360208401826001600160a01b03169052565b506040830151614e7e60408401826001600160a01b03169052565b506060830151614e9960608401826001600160a01b03169052565b506080830151614eb460808401826001600160a01b03169052565b5060a0830151614ecf60a08401826001600160a01b03169052565b5060c0830151614ee360c084018215159052565b5060e083810151908301526101008084015190830152610120808401519083015261014080840151908301526101608084015115159083015261018080840151614f2f82850182614e14565b505092915050565b600080600060c08486031215614f4c57600080fd5b614f568585614cf1565b956080850135955060a0909401359392505050565b60008060008060008060c08789031215614f8457600080fd5b863595506020870135614f9681613a5a565b94506040870135614fa681613a5a565b93506060870135614fb681613a5a565b92506080870135614fc681613a5a565b915060a0870135614fd681613c46565b809150509295509295509295565b6020808252600b908201526a4c69717569646174696e6760a81b604082015260600190565b600081518084526020808501945080840160005b838110156150425781516001600160a01b03168752958201959082019060010161501d565b509495945050505050565b6060815260006150606060830186615009565b82810360208401526150728186615009565b91505060018060a01b0383166040830152949350505050565b6000602080838503121561509e57600080fd5b82516001600160401b038111156150b457600080fd5b8301601f810185136150c557600080fd5b80516150d3613a9b82613a37565b81815260059190911b820183019083810190878311156150f257600080fd5b928401925b8284101561373e578351825292840192908401906150f7565b60208082526015908201527424b73b30b634b221b0b6363130b1b5a9b2b73232b960591b604082015260600190565b60006020828403121561515157600080fd5b8151612e0a81613c46565b6020808252601390820152724f6e6c795472616465724f72466163746f727960681b604082015260600190565b60005b838110156151a457818101518382015260200161518c565b50506000910152565b600081518084526151c5816020860160208601615189565b601f01601f19169290920160200192915050565b634e487b7160e01b600052602160045260246000fd5b6008811061520d57634e487b7160e01b600052602160045260246000fd5b9052565b82815260406020820152600082516101408060408501526152366101808501836151ad565b91506020850151606085015260408501516080850152606085015160a0850152608085015160c085015260a085015160e085015260c0850151610100818187015260e08701519150610120828188015281880151848801528088015193505050506152a56101608501826151ef565b50949350505050565b6000602082840312156152c057600080fd5b5051919050565b82815260a08101612e0a6020830184805182526020810151602083015260408101516040830152606081015160608301525050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161533a5761533a615312565b5060010190565b808202811582820484141761046657610466615312565b84815260e0810161538d6020830186805182526020810151602083015260408101516040830152606081015160608301525050565b60a082019390935260c0015292915050565b805163ffffffff8116811461079d57600080fd5b600080604083850312156153c657600080fd5b6153cf8361539f565b91506153dd6020840161539f565b90509250929050565b805161079d81613a5a565b60006020828403121561540357600080fd5b8151612e0a81613a5a565b8181038181111561046657610466615312565b8082018082111561046657610466615312565b6001600160a01b038316815281516102a0820190615477906020840190805182526020810151602083015260408101516040830152606081015160608301525050565b602083015160a083810191909152604084015160c080850191909152606085015160e0808601919091526080860151610100808701919091529286015161012080870191909152918601516101408087019190915290860151610160808701919091529286015161018080870191909152918601516101a080870191909152908601516101c080870191909152928601516101e080870191909152918601516102008087019190915290860151610220860152918501516102408501528401516102608401529092015161028090910152919050565b6000806000806080858703121561556357600080fd5b845161556e81613a5a565b602086015190945061557f81613a5a565b604086015190935061559081613a5a565b60608601519092506155a181613a5a565b939692955090935050565b805160ff8116811461079d57600080fd5b6000602082840312156155cf57600080fd5b610463826155ac565b6000826155f557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fd5b805166ffffffffffffff8116811461079d57600080fd5b805162ffffff8116811461079d57600080fd5b80516bffffffffffffffffffffffff8116811461079d57600080fd5b80516001600160801b038116811461079d57600080fd5b6000610400828403121561568057600080fd5b6156886139e4565b82518152615698602084016153e6565b60208201526156a9604084016155ac565b60408201526156ba606084016155ac565b60608201526156cb60808401615610565b60808201526156dc60a08401615627565b60a08201526156ed60c0840161539f565b60c08201526156fe60e0840161539f565b60e082015261010061571181850161539f565b9082015261012061572384820161539f565b9082015261014061573584820161539f565b908201526101606157478482016153e6565b9082015261018061575984820161539f565b908201526101a061576b8482016155ac565b908201526101c061577d84820161539f565b908201526101e061578f84820161563a565b908201526102006157a1848201615656565b908201526102206157b384820161563a565b908201526102406157c584820161539f565b908201526102606157d784820161563a565b908201526102806157e984820161563a565b908201526102a06157fb84820161563a565b908201526102c061580d84820161563a565b908201526102e061581f84820161563a565b9082015261030061583184820161563a565b9082015261032061584384820161563a565b908201526103406158558482016153e6565b9082015261036061586784820161539f565b9082015261038061587984820161539f565b908201526103a061588b84820161539f565b908201526103c061589d848201615656565b908201526103e06158af848201615656565b908201529392505050565b60ff828116828216039081111561046657610466615312565b600181815b8085111561590e5781600019048211156158f4576158f4615312565b8085161561590157918102915b93841c93908002906158d8565b509250929050565b60008261592557506001610466565b8161593257506000610466565b816001811461594857600281146159525761596e565b6001915050610466565b60ff84111561596357615963615312565b50506001821b610466565b5060208310610133831016604e8410600b8410161715615991575081810a610466565b61599b83836158d3565b80600019048211156159af576159af615312565b029392505050565b600061046360ff841683615916565b600082516159d8818460208701615189565b9190910192915050565b60208152600061046360208301846151ad56fea26469706673582212204526fb43af494063f1ce74d140a34d693196d1f14b9be8b4ab8981b2c95d1a1064736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.