Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Create Market | 6873182 | 467 days ago | IN | 0 ETH | 0.40223909 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
To
|
Amount
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 6873182 | 467 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Contract Name:
MarketFactory
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./Market.sol";
contract MarketFactory is AccessControl {
event MarketCreated(address indexed marketAddress, string marketName, address indexed baseToken, address indexed quoteToken);
// Define a role for admin users
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
struct MarketInfo {
address marketAddress;
string marketName;
address baseToken;
address quoteToken;
}
MarketInfo[] public allMarkets;
mapping(address => MarketInfo[]) public marketsByToken; // baseToken or quoteToken to market mapping
// Constructor to set up initial admin
constructor() {
_grantRole(ADMIN_ROLE, msg.sender); // Set the deployer as the default admin
}
// Function to create a new market
function createMarket(
string memory _marketName,
string memory _tradingInstrument,
address _baseToken,
address _quoteToken,
uint8 _priceDecimals
) external onlyRole(ADMIN_ROLE) returns (address) {
// Create a new market instance
Market newMarket = new Market(
_marketName,
_tradingInstrument,
_baseToken,
_quoteToken,
_priceDecimals
);
// Grant the admin role to the msg.sender
newMarket.grantRole(newMarket.DEFAULT_ADMIN_ROLE(), msg.sender);
newMarket.grantRole(newMarket.OPERATOR_ROLE(), msg.sender);
// Store market information
MarketInfo memory marketInfo = MarketInfo({
marketAddress: address(newMarket),
marketName: _marketName,
baseToken: _baseToken,
quoteToken: _quoteToken
});
allMarkets.push(marketInfo);
// Add the market to baseToken and quoteToken mappings
marketsByToken[_baseToken].push(marketInfo);
marketsByToken[_quoteToken].push(marketInfo);
// Emit the market creation event
emit MarketCreated(address(newMarket), _marketName, _baseToken, _quoteToken);
return address(newMarket);
}
// Function to get all created markets
function getAllMarkets() external view returns (MarketInfo[] memory) {
return allMarkets;
}
// Function to query markets by baseToken or quoteToken
function getMarketsByToken(address token) external view returns (MarketInfo[] memory) {
return marketsByToken[token];
}
// Function to add a new admin (only accessible by current admins)
function addAdmin(address newAdmin) external onlyRole(DEFAULT_ADMIN_ROLE) {
grantRole(ADMIN_ROLE, newAdmin);
}
// Function to remove an admin (only accessible by current admins)
function removeAdmin(address admin) external onlyRole(DEFAULT_ADMIN_ROLE) {
revokeRole(ADMIN_ROLE, admin);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @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.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @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 revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @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.
*/
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 `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @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 towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (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 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 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.
uint256 twos = denominator & (0 - denominator);
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 (unsignedRoundsUp(rounding) && 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
* towards zero.
*
* 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* 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 256, 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// 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 Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract Heap is AccessControl {
enum HeapType { MIN_HEAP, MAX_HEAP }
uint256[] public heap;
bytes32 public constant MARKET_ROLE = keccak256("MARKET_ROLE");
HeapType public heapType;
constructor(HeapType _type, address marketAddress) {
heap.push(0); // Dummy value at index 0
heapType = _type;
_grantRole(MARKET_ROLE, marketAddress);
}
function insert(uint256 _value) public onlyRole(MARKET_ROLE) {
// Add the value to the end of our array
heap.push(_value);
// Start at the end of the array
uint256 currentIndex = heap.length - 1;
// Bubble up the value until it reaches it's correct place (i.e. it is smaller than it's parent)
while(currentIndex > 1 && !compare(heap[currentIndex / 2],heap[currentIndex])) {
// If the parent value is lower/larger than our current value, we swap them
(heap[currentIndex / 2], heap[currentIndex]) = (_value, heap[currentIndex / 2]);
// change our current Index to go up to the parent
currentIndex = currentIndex / 2;
}
}
function removeRoot() public onlyRole(MARKET_ROLE) returns(uint256) {
// Ensure the heap exists
require(heap.length > 1);
// take the root value of the heap
uint256 toReturn = heap[1];
// Takes the last element of the array and put it at the root
heap[1] = heap[heap.length - 1];
// Delete the last element from the array
heap.pop();
// Start at the top
uint256 currentIndex = 1;
// Bubble down
while(currentIndex * 2 < heap.length - 1) {
// get the current index of the children
uint256 j = currentIndex * 2;
// left child value
uint256 leftChild = heap[j];
// right child value
uint256 rightChild = heap[j + 1];
// Compare the left and right child. if the rightChild is greater, then point j to it's index
if (!compare(leftChild, rightChild)) {
j = j + 1;
}
// compare the current parent value with the highest child, if the parent is greater, we're done
if(compare(heap[currentIndex], heap[j])) {
break;
}
// else swap the value
(heap[currentIndex], heap[j]) = (heap[j], heap[currentIndex]);
// and let's keep going down the heap
currentIndex = j;
}
// finally, return the top of the heap
return toReturn;
}
function getHeap() public view returns(uint256[] memory) {
return heap;
}
function getRoot() public view returns (uint256) {
if (heap.length > 1) {
return heap[1];
} else {
return 0;
}
}
function compare(uint256 child, uint256 parent) internal view returns (bool) {
return (heapType == HeapType.MIN_HEAP) ? child < parent : child > parent;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./Heap.sol"; // Import the unified Heap contract
contract Market is AccessControl, ReentrancyGuard {
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
string public marketName;
string public tradingInstrument;
address public baseToken; // Address of the base token
address public quoteToken; // Address of the quote token
uint256 public priceDenominator; // Denominator for price
enum OrderDirection { ASK, BID }
enum OrderStatus { NONE, ACTIVE, FILLED, CANCELED, EXPIRED, INSUFFICIENT_FUNDS }
enum OrderUpdateType { CREATED, PARTIALLY_FILLED, FILLED, TERMINATED }
struct Order {
address owner;
uint256 price;
uint256 initialAmount;
uint256 remainingAmount;
OrderDirection direction;
uint256 orderId;
uint256 createdAt;
uint256 validUntil;
OrderStatus status;
}
event OrderUpdate(
uint256 orderId,
address owner,
uint256 price,
uint256 initialAmount,
uint256 remainingAmount,
OrderDirection direction,
OrderStatus status,
OrderUpdateType updateType,
uint256 createdAt,
uint256 validUntil
);
event TradeCreated(
address askAddress,
address bidAddress,
uint256 price,
uint256 amount,
uint256 askOrderId,
uint256 bidOrderId
);
mapping(uint256 => Order) public ordersById;
mapping(uint256 => uint256[]) public askPriceOrders;
mapping(uint256 => uint256[]) public bidPriceOrders;
Heap public askPriceHeap;
Heap public bidPriceHeap;
uint256 public nextOrderId;
constructor(
string memory _marketName,
string memory _tradingInstrument,
address _baseToken,
address _quoteToken,
uint8 _priceDecimals
) {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(OPERATOR_ROLE, msg.sender);
marketName = _marketName;
tradingInstrument = _tradingInstrument;
baseToken = _baseToken;
quoteToken = _quoteToken;
priceDenominator = 10 ** _priceDecimals;
// Create the ask and bid heaps
askPriceHeap = new Heap(Heap.HeapType.MIN_HEAP, address(this));
bidPriceHeap = new Heap(Heap.HeapType.MAX_HEAP, address(this));
nextOrderId = 1;
}
// Function to calculate quote token amount based on base token amount and price
function calculateQuoteTokenAmount(
uint256 _baseTokenAmount,
uint256 _price,
uint256 _priceDenominator
) internal pure returns (uint256) {
return Math.mulDiv(_baseTokenAmount, _price, _priceDenominator);
}
function isFundsAvailable(address owner, uint256 amount, uint256 price, OrderDirection direction) internal view returns (bool) {
if (direction == OrderDirection.ASK) {
uint256 quoteAmount = calculateQuoteTokenAmount(amount, price, priceDenominator);
return IERC20(quoteToken).balanceOf(owner) >= quoteAmount;
} else {
return IERC20(baseToken).balanceOf(owner) >= amount;
}
}
function placeOrder(OrderDirection direction, uint256 price, uint256 amount, uint256 validBlkNum) public {
uint256 quoteTokenAmount = calculateQuoteTokenAmount(amount, price, priceDenominator);
require(quoteTokenAmount > 0, "Quote token amount must be greater than zero");
require(isFundsAvailable(msg.sender, amount, price, direction), "Insufficient funds");
require(amount > 0, "Amount must be greater than zero");
uint256 validUntil = validBlkNum + block.number;
Order memory newOrder = Order({
owner: msg.sender,
price: price,
initialAmount: amount,
remainingAmount: amount,
direction: direction,
orderId: nextOrderId,
createdAt: block.number,
validUntil: validUntil,
status: OrderStatus.ACTIVE
});
if (direction == OrderDirection.ASK) {
askPriceOrders[price].push(nextOrderId);
askPriceHeap.insert(price);
} else {
bidPriceOrders[price].push(nextOrderId);
bidPriceHeap.insert(price);
}
ordersById[nextOrderId] = newOrder;
emit OrderUpdate(nextOrderId, msg.sender, price, amount, amount, direction, OrderStatus.ACTIVE, OrderUpdateType.CREATED, block.number, validUntil);
nextOrderId++;
}
function cancelOrder(uint256 orderId) public {
Order storage order = ordersById[orderId];
require(order.owner == msg.sender, "You do not own this order");
// Changing the order status to CANCELED
removeOrder(orderId, OrderStatus.CANCELED);
}
function updateAllOrders() public onlyRole(OPERATOR_ROLE) {
for (uint256 orderId = 1; orderId < nextOrderId; orderId++) {
Order storage order = ordersById[orderId];
if (order.status == OrderStatus.ACTIVE) {
if (block.number > order.validUntil) {
removeOrder(orderId, OrderStatus.EXPIRED);
} else if (!isFundsAvailable(order.owner, order.remainingAmount, order.price, order.direction)) {
removeOrder(orderId, OrderStatus.INSUFFICIENT_FUNDS);
} else if (order.remainingAmount == 0) {
removeOrder(orderId, OrderStatus.FILLED);
}
}
}
}
function batchPlaceOrders(
OrderDirection[] memory directions,
uint256[] memory prices,
uint256[] memory amounts,
uint256[] memory validBlkNums
) public {
require(directions.length == prices.length, "Arrays must have the same length");
require(prices.length == amounts.length, "Arrays must have the same length");
require(amounts.length == validBlkNums.length, "Arrays must have the same length");
for (uint256 i = 0; i < directions.length; i++) {
placeOrder(directions[i], prices[i], amounts[i], validBlkNums[i]);
}
}
function batchCancelOrders(uint256[] memory orderIds) public {
for (uint256 i = 0; i < orderIds.length; i++) {
cancelOrder(orderIds[i]);
}
}
function processOrderFill(Order storage order, uint256 fillAmount) private {
order.remainingAmount -= fillAmount;
if (order.remainingAmount == 0) {
removeOrder(order.orderId, OrderStatus.FILLED);
} else {
emit OrderUpdate(
order.orderId,
order.owner,
order.price,
order.initialAmount,
order.remainingAmount,
order.direction,
OrderStatus.ACTIVE,
OrderUpdateType.PARTIALLY_FILLED,
order.createdAt,
order.validUntil
);
}
}
function removeOrder(uint256 orderId, OrderStatus newStatus) private {
Order storage order = ordersById[orderId];
if (order.status != OrderStatus.ACTIVE) {
return;
}
uint256[] storage orderIds = (order.direction == OrderDirection.ASK) ? askPriceOrders[order.price] : bidPriceOrders[order.price];
// Remove order ID from the respective array
for (uint256 i = 0; i < orderIds.length; i++) {
if (orderIds[i] == orderId) {
orderIds[i] = orderIds[orderIds.length - 1];
orderIds.pop();
break;
}
}
order.status = newStatus; // Mark the order as inactive
emit OrderUpdate(order.orderId, order.owner, order.price, order.initialAmount, 0, order.direction, order.status, OrderUpdateType.TERMINATED, order.createdAt, order.validUntil);
}
function isOrderIdValid(uint256 orderId) internal view returns (bool) {
return ordersById[orderId].status == OrderStatus.ACTIVE;
}
function matchOrders() public onlyRole(OPERATOR_ROLE) {
updateAllOrders();
while (true) {
uint256 minAsk = askPriceHeap.getRoot();
uint256 maxBid = bidPriceHeap.getRoot();
if (minAsk > 0 && maxBid > 0 && maxBid >= minAsk) {
uint256 askOrderId = getNextValidOrder(askPriceOrders[minAsk]);
uint256 bidOrderId = getNextValidOrder(bidPriceOrders[maxBid]);
if (!isOrderIdValid(askOrderId)) {
askPriceHeap.removeRoot();
continue;
}
if (!isOrderIdValid(bidOrderId)) {
bidPriceHeap.removeRoot();
continue;
}
Order storage askOrder = ordersById[askOrderId];
Order storage bidOrder = ordersById[bidOrderId];
uint256 askAmount = askOrder.remainingAmount;
uint256 bidAmount = bidOrder.remainingAmount;
uint256 filledAmount = (askAmount < bidAmount) ? askAmount : bidAmount;
processOrderFill(askOrder, filledAmount);
processOrderFill(bidOrder, filledAmount);
// transfer the token from the bidder to the asker
makeTradeTransfer(askOrder.owner, bidOrder.owner, filledAmount, askOrder.price);
emit TradeCreated(askOrder.owner, bidOrder.owner, askOrder.price, filledAmount, askOrder.orderId, bidOrder.orderId);
} else {
break;
}
}
}
function getNextValidOrder(uint256[] storage orderIds) private view returns (uint256) {
for (uint256 i = 0; i < orderIds.length; i++) {
if (isOrderIdValid(orderIds[i])) {
return orderIds[i];
}
}
return 0;
}
function getOpenOrderIds(address user) public view returns (uint256[] memory) {
uint256 totalActiveOrders = 0;
uint256[] memory tempOrderIds = new uint256[](nextOrderId);
for (uint256 orderId = 1; orderId < nextOrderId; orderId++) {
Order storage order = ordersById[orderId];
if (order.status == OrderStatus.ACTIVE && block.number <= order.validUntil) {
if (user == address(0) || order.owner == user) {
tempOrderIds[totalActiveOrders] = orderId;
totalActiveOrders++;
}
}
}
uint256[] memory activeOrderIds = new uint256[](totalActiveOrders);
for (uint256 i = 0; i < totalActiveOrders; i++) {
activeOrderIds[i] = tempOrderIds[i];
}
return activeOrderIds;
}
function getOpenOrders(address user) public view returns (Order[] memory) {
uint256[] memory orderIds = getOpenOrderIds(user);
Order[] memory orders = new Order[](orderIds.length);
for (uint256 i = 0; i < orderIds.length; i++) {
orders[i] = ordersById[orderIds[i]];
}
return orders;
}
function makeTradeTransfer(
address askAddress, // Address of the asker
address bidAddress, // Address of the bidder
uint256 amount,
uint256 price
) internal {
require(askAddress != address(0), "Invalid asker address");
require(bidAddress != address(0), "Invalid bidder address");
require(amount > 0, "Amount must be greater than zero");
require(price > 0, "Price must be greater than zero");
// Calculate quote token amount based on base token amount and price
uint256 quoteAmount = calculateQuoteTokenAmount(amount, price, priceDenominator);
// Transfer quoteToken from the bidder to the asker
IERC20(quoteToken).transferFrom(bidAddress, askAddress, quoteAmount);
// Transfer baseToken from the asker to the bidder
IERC20(baseToken).transferFrom(askAddress, bidAddress, amount);
}
function transferAdmin(address newAdmin) public onlyRole(DEFAULT_ADMIN_ROLE) {
require(newAdmin != address(0), "New admin address cannot be zero");
_grantRole(DEFAULT_ADMIN_ROLE, newAdmin);
_revokeRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketAddress","type":"address"},{"indexed":false,"internalType":"string","name":"marketName","type":"string"},{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":true,"internalType":"address","name":"quoteToken","type":"address"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allMarkets","outputs":[{"internalType":"address","name":"marketAddress","type":"address"},{"internalType":"string","name":"marketName","type":"string"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_marketName","type":"string"},{"internalType":"string","name":"_tradingInstrument","type":"string"},{"internalType":"address","name":"_baseToken","type":"address"},{"internalType":"address","name":"_quoteToken","type":"address"},{"internalType":"uint8","name":"_priceDecimals","type":"uint8"}],"name":"createMarket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllMarkets","outputs":[{"components":[{"internalType":"address","name":"marketAddress","type":"address"},{"internalType":"string","name":"marketName","type":"string"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"}],"internalType":"struct MarketFactory.MarketInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getMarketsByToken","outputs":[{"components":[{"internalType":"address","name":"marketAddress","type":"address"},{"internalType":"string","name":"marketName","type":"string"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"}],"internalType":"struct MarketFactory.MarketInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketsByToken","outputs":[{"internalType":"address","name":"marketAddress","type":"address"},{"internalType":"string","name":"marketName","type":"string"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6080604052348015600f57600080fd5b5060387fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177533603d565b5060e6565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1660dc576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905560953390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600160e0565b5060005b92915050565b614914806100f56000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637048027511610097578063b0772d0b11610066578063b0772d0b1461021f578063c81899a014610234578063cd94a77514610247578063d547741f1461025a57600080fd5b806370480275146101dc57806375b238fc146101ef57806391d1485414610204578063a217fddf1461021757600080fd5b8063248a9ca3116100d3578063248a9ca3146101625780632f2ff15d1461019357806336568abe146101a657806352d84d1e146101b957600080fd5b806301ffc9a7146100fa578063032b6be3146101225780631785f53c1461014d575b600080fd5b61010d610108366004610cd1565b61026d565b60405190151581526020015b60405180910390f35b610135610130366004610dc3565b6102a4565b6040516001600160a01b039091168152602001610119565b61016061015b366004610e68565b6106ea565b005b610185610170366004610e83565b60009081526020819052604090206001015490565b604051908152602001610119565b6101606101a1366004610e9c565b610711565b6101606101b4366004610e9c565b61073c565b6101cc6101c7366004610e83565b610774565b6040516101199493929190610f0e565b6101606101ea366004610e68565b61084f565b6101856000805160206148bf83398151915281565b61010d610212366004610e9c565b610872565b610185600081565b61022761089b565b6040516101199190610f53565b6101cc610242366004610ffd565b6109c8565b610227610255366004610e68565b610a15565b610160610268366004610e9c565b610b58565b60006001600160e01b03198216637965db0b60e01b148061029e57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60006000805160206148bf8339815191526102be81610b7d565b600087878787876040516102d190610cc4565b6102df959493929190611027565b604051809103906000f0801580156102fb573d6000803e3d6000fd5b509050806001600160a01b0316632f2ff15d826001600160a01b031663a217fddf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561034b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061036f9190611079565b6040516001600160e01b031960e084901b1681526004810191909152336024820152604401600060405180830381600087803b1580156103ae57600080fd5b505af11580156103c2573d6000803e3d6000fd5b50505050806001600160a01b0316632f2ff15d826001600160a01b031663f5b541a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610413573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104379190611079565b6040516001600160e01b031960e084901b1681526004810191909152336024820152604401600060405180830381600087803b15801561047657600080fd5b505af115801561048a573d6000803e3d6000fd5b5050604080516080810182526001600160a01b038581168252602082018d81528b821693830193909352898116606083015260018054808201825560009190915282517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6600490920291820180546001600160a01b031916919093161782559251919450849350917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7019061053f908261111a565b50604082810151600283810180546001600160a01b03199081166001600160a01b0394851617909155606090950151600390940180548616948316949094179093558a811660009081526020938452918220805460018181018355918452928490208651600490940201805490951692909116919091178355908301518392918201906105cc908261111a565b50604082810151600283810180546001600160a01b03199081166001600160a01b0394851617909155606090950151600390940180548616948316949094179093558981166000908152602093845291822080546001818101835591845292849020865160049094020180549095169290911691909117835590830151839291820190610659908261111a565b506040828101516002830180546001600160a01b03199081166001600160a01b0393841617909155606090940151600390930180549094169281169290921790925590518782169189811691908516907feb1241664226e3def099aec58d10dc3e7fe1402293e98d322a05829e9e763d8b906106d6908e906111d9565b60405180910390a450979650505050505050565b60006106f581610b7d565b61070d6000805160206148bf83398151915283610b58565b5050565b60008281526020819052604090206001015461072c81610b7d565b6107368383610b8a565b50505050565b6001600160a01b03811633146107655760405163334bd91960e11b815260040160405180910390fd5b61076f8282610c1c565b505050565b6001818154811061078457600080fd5b6000918252602090912060049091020180546001820180546001600160a01b039092169350906107b390611092565b80601f01602080910402602001604051908101604052809291908181526020018280546107df90611092565b801561082c5780601f106108015761010080835404028352916020019161082c565b820191906000526020600020905b81548152906001019060200180831161080f57829003601f168201915b50505050600283015460039093015491926001600160a01b039081169216905084565b600061085a81610b7d565b61070d6000805160206148bf83398151915283610711565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606001805480602002602001604051908101604052809291908181526020016000905b828210156109bf57600084815260209081902060408051608081019091526004850290910180546001600160a01b03168252600181018054929391929184019161090890611092565b80601f016020809104026020016040519081016040528092919081815260200182805461093490611092565b80156109815780601f1061095657610100808354040283529160200191610981565b820191906000526020600020905b81548152906001019060200180831161096457829003601f168201915b505050918352505060028201546001600160a01b039081166020808401919091526003909301541660409091015290825260019290920191016108bf565b50505050905090565b600260205281600052604060002081815481106109e457600080fd5b6000918252602090912060049091020180546001820180546001600160a01b0390921694509192506107b390611092565b6001600160a01b0381166000908152600260209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610b4d57600084815260209081902060408051608081019091526004850290910180546001600160a01b031682526001810180549293919291840191610a9690611092565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac290611092565b8015610b0f5780601f10610ae457610100808354040283529160200191610b0f565b820191906000526020600020905b815481529060010190602001808311610af257829003601f168201915b505050918352505060028201546001600160a01b03908116602080840191909152600390930154166040909101529082526001929092019101610a4d565b505050509050919050565b600082815260208190526040902060010154610b7381610b7d565b6107368383610c1c565b610b878133610c87565b50565b6000610b968383610872565b610c14576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610bcc3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161029e565b50600061029e565b6000610c288383610872565b15610c14576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161029e565b610c918282610872565b61070d5760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b6136d2806111ed83390190565b600060208284031215610ce357600080fd5b81356001600160e01b031981168114610cfb57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610d2957600080fd5b813567ffffffffffffffff811115610d4357610d43610d02565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610d7257610d72610d02565b604052818152838201602001851015610d8a57600080fd5b816020850160208301376000918101602001919091529392505050565b80356001600160a01b0381168114610dbe57600080fd5b919050565b600080600080600060a08688031215610ddb57600080fd5b853567ffffffffffffffff811115610df257600080fd5b610dfe88828901610d18565b955050602086013567ffffffffffffffff811115610e1b57600080fd5b610e2788828901610d18565b945050610e3660408701610da7565b9250610e4460608701610da7565b9150608086013560ff81168114610e5a57600080fd5b809150509295509295909350565b600060208284031215610e7a57600080fd5b610cfb82610da7565b600060208284031215610e9557600080fd5b5035919050565b60008060408385031215610eaf57600080fd5b82359150610ebf60208401610da7565b90509250929050565b6000815180845260005b81811015610eee57602081850181015186830182015201610ed2565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152608060208201819052600090610f3290830186610ec8565b6001600160a01b039485166040840152929093166060909101529392505050565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610ff157868503603f19018452815180516001600160a01b03168652602080820151608091880182905290610fb690880182610ec8565b6040838101516001600160a01b03908116918a0191909152606093840151169290970191909152506020938401939190910190600101610f7b565b50929695505050505050565b6000806040838503121561101057600080fd5b61101983610da7565b946020939093013593505050565b60a08152600061103a60a0830188610ec8565b828103602084015261104c8188610ec8565b6001600160a01b0396871660408501529490951660608301525060ff919091166080909101529392505050565b60006020828403121561108b57600080fd5b5051919050565b600181811c908216806110a657607f821691505b6020821081036110c657634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561076f57806000526020600020601f840160051c810160208510156110f35750805b601f840160051c820191505b8181101561111357600081556001016110ff565b5050505050565b815167ffffffffffffffff81111561113457611134610d02565b611148816111428454611092565b846110cc565b6020601f82116001811461117c57600083156111645750848201515b600019600385901b1c1916600184901b178455611113565b600084815260208120601f198516915b828110156111ac578785015182556020948501946001909201910161118c565b50848210156111ca5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b602081526000610cfb6020830184610ec856fe608060405234801561001057600080fd5b506040516136d23803806136d283398101604081905261002f91610316565b6001805561003e600033610188565b506100697f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92933610188565b5060026100768682610444565b5060036100838582610444565b50600480546001600160a01b038086166001600160a01b03199283161790925560058054928516929091169190911790556100bf81600a6105ff565b60065560405160009030906100d390610234565b6100de929190610615565b604051809103906000f0801580156100fa573d6000803e3d6000fd5b50600a60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060013060405161013090610234565b61013b929190610615565b604051809103906000f080158015610157573d6000803e3d6000fd5b50600b80546001600160a01b0319166001600160a01b039290921691909117905550506001600c555061064f915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1661022a576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101e23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161022e565b5060005b92915050565b610c8380612a4f83390190565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261026857600080fd5b81516001600160401b0381111561028157610281610241565b604051601f8201601f19908116603f011681016001600160401b03811182821017156102af576102af610241565b6040528181528382016020018510156102c757600080fd5b60005b828110156102e6576020818601810151838301820152016102ca565b506000918101602001919091529392505050565b80516001600160a01b038116811461031157600080fd5b919050565b600080600080600060a0868803121561032e57600080fd5b85516001600160401b0381111561034457600080fd5b61035088828901610257565b602088015190965090506001600160401b0381111561036e57600080fd5b61037a88828901610257565b945050610389604087016102fa565b9250610397606087016102fa565b9150608086015160ff811681146103ad57600080fd5b809150509295509295909350565b600181811c908216806103cf57607f821691505b6020821081036103ef57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561043f57806000526020600020601f840160051c8101602085101561041c5750805b601f840160051c820191505b8181101561043c5760008155600101610428565b50505b505050565b81516001600160401b0381111561045d5761045d610241565b6104718161046b84546103bb565b846103f5565b6020601f8211600181146104a5576000831561048d5750848201515b600019600385901b1c1916600184901b17845561043c565b600084815260208120601f198516915b828110156104d557878501518255602094850194600190920191016104b5565b50848210156104f35786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b6001815b60018411156105535780850481111561053757610537610502565b600184161561054557908102905b60019390931c92800261051c565b935093915050565b60008261056a5750600161022e565b816105775750600061022e565b816001811461058d5760028114610597576105b3565b600191505061022e565b60ff8411156105a8576105a8610502565b50506001821b61022e565b5060208310610133831016604e8410600b84101617156105d6575081810a61022e565b6105e36000198484610518565b80600019048211156105f7576105f7610502565b029392505050565b600061060e60ff84168361055b565b9392505050565b604081016002841061063757634e487b7160e01b600052602160045260246000fd5b9281526001600160a01b039190911660209091015290565b6123f18061065e6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806375829def116100f9578063a266f85a11610097578063d547741f11610071578063d547741f14610430578063e6bfd26a14610443578063f0dff6b61461044b578063f5b541a61461045e57600080fd5b8063a266f85a146103ff578063c55dae6314610414578063cdcf4b9b1461042757600080fd5b806386f34467116100d357806386f34467146103be5780638c29c911146103d157806391d14854146103e4578063a217fddf146103f757600080fd5b806375829def146103905780637d4feb72146103a35780637ee68546146103b657600080fd5b80632c7d413b116101665780634622c218116101405780634622c21814610342578063514fcac7146103555780636e84a27114610368578063709bfe9a1461037057600080fd5b80632c7d413b146103075780632f2ff15d1461031a57806336568abe1461032f57600080fd5b806323edfa2e116101a257806323edfa2e1461023c578063248a9ca31461025d5780632a58b330146102805780632c4cb11a1461028957600080fd5b806301ffc9a7146101c9578063049405be146101f1578063217a4b7014610211575b600080fd5b6101dc6101d7366004611ce7565b610485565b60405190151581526020015b60405180910390f35b6102046101ff366004611d2d565b6104bc565b6040516101e89190611d82565b600554610224906001600160a01b031681565b6040516001600160a01b0390911681526020016101e8565b61024f61024a366004611e3a565b61066a565b6040519081526020016101e8565b61024f61026b366004611e5c565b60009081526020819052604090206001015490565b61024f600c5481565b6102f2610297366004611e5c565b60076020819052600091825260409091208054600182015460028301546003840154600485015460058601546006870154978701546008909701546001600160a01b039096169794969395929460ff92831694919390921689565b6040516101e899989796959493929190611e75565b61024f610315366004611e3a565b61069b565b61032d610328366004611ed6565b6106b7565b005b61032d61033d366004611ed6565b6106e2565b61032d610350366004611f11565b61071a565b61032d610363366004611e5c565b610aff565b61032d610b75565b61038361037e366004611d2d565b610c4e565b6040516101e89190611f4a565b61032d61039e366004611d2d565b610ddd565b61032d6103b136600461205a565b610e55565b61032d610e8b565b600b54610224906001600160a01b031681565b61032d6103df36600461208f565b6111dc565b6101dc6103f2366004611ed6565b6112ca565b61024f600081565b6104076112f3565b6040516101e891906121af565b600454610224906001600160a01b031681565b61024f60065481565b61032d61043e366004611ed6565b611381565b6104076113a6565b600a54610224906001600160a01b031681565b61024f7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92981565b60006001600160e01b03198216637965db0b60e01b14806104b657506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060006104c983610c4e565b90506000815167ffffffffffffffff8111156104e7576104e7611f82565b60405190808252806020026020018201604052801561052057816020015b61050d611c71565b8152602001906001900390816105055790505b50905060005b82518110156106625760076000848381518110610545576105456121fd565b60200260200101518152602001908152602001600020604051806101200160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1660018111156105d8576105d8611d48565b60018111156105e9576105e9611d48565b815260058281015460208301526006830154604083015260078301546060830152600883015460809092019160ff169081111561062857610628611d48565b600581111561063957610639611d48565b8152505082828151811061064f5761064f6121fd565b6020908102919091010152600101610526565b509392505050565b6009602052816000526040600020818154811061068657600080fd5b90600052602060002001600091509150505481565b6008602052816000526040600020818154811061068657600080fd5b6000828152602081905260409020600101546106d2816113b3565b6106dc83836113bd565b50505050565b6001600160a01b038116331461070b5760405163334bd91960e11b815260040160405180910390fd5b610715828261144f565b505050565b600061072983856006546114ba565b9050600081116107955760405162461bcd60e51b815260206004820152602c60248201527f51756f746520746f6b656e20616d6f756e74206d75737420626520677265617460448201526b6572207468616e207a65726f60a01b60648201526084015b60405180910390fd5b6107a1338486886114d1565b6107e25760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b604482015260640161078c565b600083116108325760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015260640161078c565b600061083e4384612229565b90506000604051806101200160405280336001600160a01b0316815260200187815260200186815260200186815260200188600181111561088157610881611d48565b8152600c5460208201524360408201526060810184905260800160019052905060008760018111156108b5576108b5611d48565b03610943576000868152600860209081526040808320600c5481546001810183559185529290932090920155600a5490516390b5561d60e01b8152600481018890526001600160a01b03909116906390b5561d90602401600060405180830381600087803b15801561092657600080fd5b505af115801561093a573d6000803e3d6000fd5b505050506109c8565b6000868152600960209081526040808320600c5481546001810183559185529290932090920155600b5490516390b5561d60e01b8152600481018890526001600160a01b03909116906390b5561d90602401600060405180830381600087803b1580156109af57600080fd5b505af11580156109c3573d6000803e3d6000fd5b505050505b600c54600090815260076020908152604091829020835181546001600160a01b0319166001600160a01b0390911617815590830151600180830191909155918301516002820155606083015160038201556080830151600482018054859460ff19909116908381811115610a3e57610a3e611d48565b021790555060a0820151816005015560c0820151816006015560e082015181600701556101008201518160080160006101000a81548160ff02191690836005811115610a8c57610a8c611d48565b02179055509050507fc61479f640c5df729563b3ae73c6592bfaef0f2f68133af5b287fc6bc1635cf5600c54338888898c60016000438b604051610ad99a9998979695949392919061224c565b60405180910390a1600c8054906000610af1836122b9565b919050555050505050505050565b600081815260076020526040902080546001600160a01b03163314610b665760405162461bcd60e51b815260206004820152601960248201527f596f7520646f206e6f74206f776e2074686973206f7264657200000000000000604482015260640161078c565b610b718260036115f7565b5050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b929610b9f816113b3565b60015b600c54811015610b715760008181526007602052604090206001600882015460ff166005811115610bd557610bd5611d48565b03610c45578060070154431115610bf657610bf18260046115f7565b610c45565b8054600382015460018301546004840154610c1f936001600160a01b031692919060ff166114d1565b610c2e57610bf18260056115f7565b8060030154600003610c4557610c458260026115f7565b50600101610ba2565b6060600080600c5467ffffffffffffffff811115610c6e57610c6e611f82565b604051908082528060200260200182016040528015610c97578160200160208202803683370190505b50905060015b600c54811015610d425760008181526007602052604090206001600882015460ff166005811115610cd057610cd0611d48565b148015610ce1575080600701544311155b15610d39576001600160a01b0386161580610d08575080546001600160a01b038781169116145b15610d395781838581518110610d2057610d206121fd565b602090810291909101015283610d35816122b9565b9450505b50600101610c9d565b5060008267ffffffffffffffff811115610d5e57610d5e611f82565b604051908082528060200260200182016040528015610d87578160200160208202803683370190505b50905060005b83811015610dd457828181518110610da757610da76121fd565b6020026020010151828281518110610dc157610dc16121fd565b6020908102919091010152600101610d8d565b50949350505050565b6000610de8816113b3565b6001600160a01b038216610e3e5760405162461bcd60e51b815260206004820181905260248201527f4e65772061646d696e20616464726573732063616e6e6f74206265207a65726f604482015260640161078c565b610e496000836113bd565b5061071560003361144f565b60005b8151811015610b7157610e83828281518110610e7657610e766121fd565b6020026020010151610aff565b600101610e58565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b929610eb5816113b3565b610ebd610b75565b600a5460408051635ca1e16560e01b815290516000926001600160a01b031691635ca1e1659160048083019260209291908290030181865afa158015610f07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2b91906122d2565b90506000600b60009054906101000a90046001600160a01b03166001600160a01b0316635ca1e1656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa691906122d2565b9050600082118015610fb85750600081115b8015610fc45750818110155b15610715576000828152600860205260408120610fe0906117d2565b600083815260096020526040812091925090610ffb906117d2565b90506110068261183f565b61108d57600a60009054906101000a90046001600160a01b03166001600160a01b0316633351cc736040518163ffffffff1660e01b81526004016020604051808303816000875af115801561105f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108391906122d2565b5050505050610ebd565b6110968161183f565b6110ef57600b60009054906101000a90046001600160a01b03166001600160a01b0316633351cc736040518163ffffffff1660e01b81526004016020604051808303816000875af115801561105f573d6000803e3d6000fd5b600082815260076020526040808220838352908220600380830154908201549293919290918183106111215781611123565b825b905061112f8582611870565b6111398482611870565b84548454600187015461115b926001600160a01b03908116921690849061191d565b84548454600187015460058089015490880154604080516001600160a01b0396871681529590941660208601528484019290925260608401859052608084015260a0830152517f532c61a7371ced9ca44dc5bb81f73a24cb3d0af8f4396a3d03c3db699be662939181900360c00190a1505050505050505050610ebd565b50565b82518451146111fd5760405162461bcd60e51b815260040161078c906122eb565b815183511461121e5760405162461bcd60e51b815260040161078c906122eb565b805182511461123f5760405162461bcd60e51b815260040161078c906122eb565b60005b84518110156112c3576112bb858281518110611260576112606121fd565b602002602001015185838151811061127a5761127a6121fd565b6020026020010151858481518110611294576112946121fd565b60200260200101518585815181106112ae576112ae6121fd565b602002602001015161071a565b600101611242565b5050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6003805461130090612320565b80601f016020809104026020016040519081016040528092919081815260200182805461132c90612320565b80156113795780601f1061134e57610100808354040283529160200191611379565b820191906000526020600020905b81548152906001019060200180831161135c57829003601f168201915b505050505081565b60008281526020819052604090206001015461139c816113b3565b6106dc838361144f565b6002805461130090612320565b6111d98133611b74565b60006113c983836112ca565b611447576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556113ff3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016104b6565b5060006104b6565b600061145b83836112ca565b15611447576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016104b6565b60006114c7848484611bad565b90505b9392505050565b6000808260018111156114e6576114e6611d48565b036115775760006114fa85856006546114ba565b6005546040516370a0823160e01b81526001600160a01b0389811660048301529293508392909116906370a0823190602401602060405180830381865afa158015611549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156d91906122d2565b10159150506115ef565b600480546040516370a0823160e01b81526001600160a01b03888116938201939093528692909116906370a0823190602401602060405180830381865afa1580156115c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ea91906122d2565b101590505b949350505050565b60008281526007602052604090206001600882015460ff16600581111561162057611620611d48565b1461162a57505050565b600080600483015460ff16600181111561164657611646611d48565b146116635760018201546000908152600960205260409020611677565b600182015460009081526008602052604090205b905060005b81548110156117265784828281548110611698576116986121fd565b90600052602060002001540361171e57815482906116b89060019061235a565b815481106116c8576116c86121fd565b90600052602060002001548282815481106116e5576116e56121fd565b9060005260206000200181905550818054806117035761170361236d565b60019003818190600052602060002001600090559055611726565b60010161167c565b5060088201805484919060ff1916600183600581111561174857611748611d48565b0217905550600582015482546001840154600285015460048601546008870154600688015460078901546040517fc61479f640c5df729563b3ae73c6592bfaef0f2f68133af5b287fc6bc1635cf5986117c49890976001600160a01b03909116969095909460009460ff9283169492909116926003929061224c565b60405180910390a150505050565b6000805b8254811015611836576118048382815481106117f4576117f46121fd565b906000526020600020015461183f565b1561182e5782818154811061181b5761181b6121fd565b9060005260206000200154915050919050565b6001016117d6565b50600092915050565b6000600160008381526007602052604090206008015460ff16600581111561186957611869611d48565b1492915050565b80826003016000828254611884919061235a565b909155505060038201546000036118a457610b71826005015460026115f7565b60058201548254600180850154600286015460038701546004880154600689015460078a01546040517fc61479f640c5df729563b3ae73c6592bfaef0f2f68133af5b287fc6bc1635cf5996119119990986001600160a01b039091169796959460ff16939092839261224c565b60405180910390a15050565b6001600160a01b03841661196b5760405162461bcd60e51b8152602060048201526015602482015274496e76616c69642061736b6572206164647265737360581b604482015260640161078c565b6001600160a01b0383166119ba5760405162461bcd60e51b8152602060048201526016602482015275496e76616c696420626964646572206164647265737360501b604482015260640161078c565b60008211611a0a5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015260640161078c565b60008111611a5a5760405162461bcd60e51b815260206004820152601f60248201527f5072696365206d7573742062652067726561746572207468616e207a65726f00604482015260640161078c565b6000611a6983836006546114ba565b6005546040516323b872dd60e01b81526001600160a01b0387811660048301528881166024830152604482018490529293509116906323b872dd906064016020604051808303816000875af1158015611ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aea9190612383565b50600480546040516323b872dd60e01b81526001600160a01b03888116938201939093528683166024820152604481018690529116906323b872dd906064016020604051808303816000875af1158015611b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6c9190612383565b505050505050565b611b7e82826112ca565b610b715760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161078c565b6000838302816000198587098281108382030391505080600003611be457838281611bda57611bda6123a5565b04925050506114ca565b808411611c045760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b60405180610120016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160006001811115611cb557611cb5611d48565b815260200160008152602001600081526020016000815260200160006005811115611ce257611ce2611d48565b905290565b600060208284031215611cf957600080fd5b81356001600160e01b0319811681146114ca57600080fd5b80356001600160a01b0381168114611d2857600080fd5b919050565b600060208284031215611d3f57600080fd5b6114ca82611d11565b634e487b7160e01b600052602160045260246000fd5b60028110611d6e57611d6e611d48565b9052565b60068110611d6e57611d6e611d48565b602080825282518282018190526000918401906040840190835b81811015611e2f57835160018060a01b0381511684526020810151602085015260408101516040850152606081015160608501526080810151611de26080860182611d5e565b5060a081015160a085015260c081015160c085015260e081015160e08501526101008101519050611e17610100850182611d72565b50602093909301926101209290920191600101611d9c565b509095945050505050565b60008060408385031215611e4d57600080fd5b50508035926020909101359150565b600060208284031215611e6e57600080fd5b5035919050565b6001600160a01b038a1681526020810189905260408101889052606081018790526101208101611ea86080830188611d5e565b8560a08301528460c08301528360e0830152611ec8610100830184611d72565b9a9950505050505050505050565b60008060408385031215611ee957600080fd5b82359150611ef960208401611d11565b90509250929050565b803560028110611d2857600080fd5b60008060008060808587031215611f2757600080fd5b611f3085611f02565b966020860135965060408601359560600135945092505050565b602080825282518282018190526000918401906040840190835b81811015611e2f578351835260209384019390920191600101611f64565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611fc157611fc1611f82565b604052919050565b600067ffffffffffffffff821115611fe357611fe3611f82565b5060051b60200190565b600082601f830112611ffe57600080fd5b813561201161200c82611fc9565b611f98565b8082825260208201915060208360051b86010192508583111561203357600080fd5b602085015b83811015612050578035835260209283019201612038565b5095945050505050565b60006020828403121561206c57600080fd5b813567ffffffffffffffff81111561208357600080fd5b6115ef84828501611fed565b600080600080608085870312156120a557600080fd5b843567ffffffffffffffff8111156120bc57600080fd5b8501601f810187136120cd57600080fd5b80356120db61200c82611fc9565b8082825260208201915060208360051b8501019250898311156120fd57600080fd5b6020840193505b828410156121265761211584611f02565b825260209384019390910190612104565b9650505050602085013567ffffffffffffffff81111561214557600080fd5b61215187828801611fed565b935050604085013567ffffffffffffffff81111561216e57600080fd5b61217a87828801611fed565b925050606085013567ffffffffffffffff81111561219757600080fd5b6121a387828801611fed565b91505092959194509250565b602081526000825180602084015260005b818110156121dd57602081860181015160408684010152016121c0565b506000604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156104b6576104b6612213565b60048110611d6e57611d6e611d48565b8a81526001600160a01b038a166020820152604081018990526060810188905260808101879052610140810161228560a0830188611d5e565b61229260c0830187611d72565b61229f60e083018661223c565b610100820193909352610120015298975050505050505050565b6000600182016122cb576122cb612213565b5060010190565b6000602082840312156122e457600080fd5b5051919050565b6020808252818101527f417272617973206d7573742068617665207468652073616d65206c656e677468604082015260600190565b600181811c9082168061233457607f821691505b60208210810361235457634e487b7160e01b600052602260045260246000fd5b50919050565b818103818111156104b6576104b6612213565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561239557600080fd5b815180151581146114ca57600080fd5b634e487b7160e01b600052601260045260246000fdfea264697066735822122088b5fc18d7905a867f376b7377a2f9326d41872063d7ca4c5337c4fa85952b4264736f6c634300081b0033608060405234801561001057600080fd5b50604051610c83380380610c8383398101604081905261002f91610163565b60018054808201825560008281527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69091015560028054849260ff19909116908381811115610080576100806101ad565b02179055506100af7f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f826100b7565b5050506101c3565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16610159576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101113390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161015d565b5060005b92915050565b6000806040838503121561017657600080fd5b82516002811061018557600080fd5b60208401519092506001600160a01b03811681146101a257600080fd5b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b610ab1806101d26000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80633e27ec9b1161008c57806390b5561d1161006657806390b5561d146101e957806391d14854146101fc578063a217fddf1461020f578063d547741f1461021757600080fd5b80633e27ec9b146101a55780635ca1e165146101cc57806372394ba6146101d457600080fd5b80632e1a49cc116100c85780632e1a49cc1461015b5780632f2ff15d146101755780633351cc731461018a57806336568abe1461019257600080fd5b806301ffc9a7146100ef5780631c01f29214610117578063248a9ca314610138575b600080fd5b6101026100fd3660046108da565b61022a565b60405190151581526020015b60405180910390f35b61012a610125366004610904565b610261565b60405190815260200161010e565b61012a610146366004610904565b60009081526020819052604090206001015490565b6002546101689060ff1681565b60405161010e9190610933565b61018861018336600461095b565b610282565b005b61012a6102ad565b6101886101a036600461095b565b6104fd565b61012a7f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f81565b61012a610535565b6101dc61056b565b60405161010e9190610997565b6101886101f7366004610904565b6105c3565b61010261020a36600461095b565b61070f565b61012a600081565b61018861022536600461095b565b610738565b60006001600160e01b03198216637965db0b60e01b148061025b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6001818154811061027157600080fd5b600091825260209091200154905081565b60008281526020819052604090206001015461029d8161075d565b6102a7838361076a565b50505050565b60007f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f6102d98161075d565b60018054116102e757600080fd5b6000600180815481106102fc576102fc6109da565b90600052602060002001549050600180808054905061031b9190610a06565b8154811061032b5761032b6109da565b906000526020600020015460018081548110610349576103496109da565b600091825260209091200155600180548061036657610366610a19565b600190038181906000526020600020016000905590556000600190505b600180546103919190610a06565b61039c826002610a2f565b10156104f65760006103af826002610a2f565b90506000600182815481106103c6576103c66109da565b6000918252602082200154915060016103df8482610a46565b815481106103ef576103ef6109da565b9060005260206000200154905061040682826107fc565b61041857610415836001610a46565b92505b61045c6001858154811061042e5761042e6109da565b90600052602060002001546001858154811061044c5761044c6109da565b90600052602060002001546107fc565b15610469575050506104f6565b6001838154811061047c5761047c6109da565b90600052602060002001546001858154811061049a5761049a6109da565b9060005260206000200154600186815481106104b8576104b86109da565b906000526020600020016000600187815481106104d7576104d76109da565b6000918252602090912001929092559190915550919250610383915050565b5091505090565b6001600160a01b03811633146105265760405163334bd91960e11b815260040160405180910390fd5b610530828261082e565b505050565b6001805460009110156105655760018081548110610555576105556109da565b9060005260206000200154905090565b50600090565b606060018054806020026020016040519081016040528092919081815260200182805480156105b957602002820191906000526020600020905b8154815260200190600101908083116105a5575b5050505050905090565b7f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f6105ed8161075d565b60018054808201825560008281527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69091018490558154909161062f91610a06565b90505b60018111801561067d575061067b600161064d600284610a59565b8154811061065d5761065d6109da565b90600052602060002001546001838154811061044c5761044c6109da565b155b1561053057826001610690600284610a59565b815481106106a0576106a06109da565b906000526020600020015460016002846106ba9190610a59565b815481106106ca576106ca6109da565b906000526020600020016000600185815481106106e9576106e96109da565b6000918252602090912001929092559190915550610708600282610a59565b9050610632565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6000828152602081905260409020600101546107538161075d565b6102a7838361082e565b6107678133610899565b50565b6000610776838361070f565b6107f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556107ac3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161025b565b50600061025b565b60008060025460ff1660018111156108165761081661091d565b1461082357818311610827565b8183105b9392505050565b600061083a838361070f565b156107f4576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161025b565b6108a3828261070f565b6108d65760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b5050565b6000602082840312156108ec57600080fd5b81356001600160e01b03198116811461082757600080fd5b60006020828403121561091657600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b602081016002831061095557634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561096e57600080fd5b8235915060208301356001600160a01b038116811461098c57600080fd5b809150509250929050565b602080825282518282018190526000918401906040840190835b818110156109cf5783518352602093840193909201916001016109b1565b509095945050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561025b5761025b6109f0565b634e487b7160e01b600052603160045260246000fd5b808202811582820484141761025b5761025b6109f0565b8082018082111561025b5761025b6109f0565b600082610a7657634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212206f7843179fb6f52f6420bc6cb1a4400b62604b6fb8eee8951082630b31da04c264736f6c634300081b0033a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a264697066735822122078689d7b24144eda2b806ee00828a83bef33bb19de57809bf53ee2610d537e3f64736f6c634300081b0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80637048027511610097578063b0772d0b11610066578063b0772d0b1461021f578063c81899a014610234578063cd94a77514610247578063d547741f1461025a57600080fd5b806370480275146101dc57806375b238fc146101ef57806391d1485414610204578063a217fddf1461021757600080fd5b8063248a9ca3116100d3578063248a9ca3146101625780632f2ff15d1461019357806336568abe146101a657806352d84d1e146101b957600080fd5b806301ffc9a7146100fa578063032b6be3146101225780631785f53c1461014d575b600080fd5b61010d610108366004610cd1565b61026d565b60405190151581526020015b60405180910390f35b610135610130366004610dc3565b6102a4565b6040516001600160a01b039091168152602001610119565b61016061015b366004610e68565b6106ea565b005b610185610170366004610e83565b60009081526020819052604090206001015490565b604051908152602001610119565b6101606101a1366004610e9c565b610711565b6101606101b4366004610e9c565b61073c565b6101cc6101c7366004610e83565b610774565b6040516101199493929190610f0e565b6101606101ea366004610e68565b61084f565b6101856000805160206148bf83398151915281565b61010d610212366004610e9c565b610872565b610185600081565b61022761089b565b6040516101199190610f53565b6101cc610242366004610ffd565b6109c8565b610227610255366004610e68565b610a15565b610160610268366004610e9c565b610b58565b60006001600160e01b03198216637965db0b60e01b148061029e57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60006000805160206148bf8339815191526102be81610b7d565b600087878787876040516102d190610cc4565b6102df959493929190611027565b604051809103906000f0801580156102fb573d6000803e3d6000fd5b509050806001600160a01b0316632f2ff15d826001600160a01b031663a217fddf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561034b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061036f9190611079565b6040516001600160e01b031960e084901b1681526004810191909152336024820152604401600060405180830381600087803b1580156103ae57600080fd5b505af11580156103c2573d6000803e3d6000fd5b50505050806001600160a01b0316632f2ff15d826001600160a01b031663f5b541a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610413573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104379190611079565b6040516001600160e01b031960e084901b1681526004810191909152336024820152604401600060405180830381600087803b15801561047657600080fd5b505af115801561048a573d6000803e3d6000fd5b5050604080516080810182526001600160a01b038581168252602082018d81528b821693830193909352898116606083015260018054808201825560009190915282517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6600490920291820180546001600160a01b031916919093161782559251919450849350917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7019061053f908261111a565b50604082810151600283810180546001600160a01b03199081166001600160a01b0394851617909155606090950151600390940180548616948316949094179093558a811660009081526020938452918220805460018181018355918452928490208651600490940201805490951692909116919091178355908301518392918201906105cc908261111a565b50604082810151600283810180546001600160a01b03199081166001600160a01b0394851617909155606090950151600390940180548616948316949094179093558981166000908152602093845291822080546001818101835591845292849020865160049094020180549095169290911691909117835590830151839291820190610659908261111a565b506040828101516002830180546001600160a01b03199081166001600160a01b0393841617909155606090940151600390930180549094169281169290921790925590518782169189811691908516907feb1241664226e3def099aec58d10dc3e7fe1402293e98d322a05829e9e763d8b906106d6908e906111d9565b60405180910390a450979650505050505050565b60006106f581610b7d565b61070d6000805160206148bf83398151915283610b58565b5050565b60008281526020819052604090206001015461072c81610b7d565b6107368383610b8a565b50505050565b6001600160a01b03811633146107655760405163334bd91960e11b815260040160405180910390fd5b61076f8282610c1c565b505050565b6001818154811061078457600080fd5b6000918252602090912060049091020180546001820180546001600160a01b039092169350906107b390611092565b80601f01602080910402602001604051908101604052809291908181526020018280546107df90611092565b801561082c5780601f106108015761010080835404028352916020019161082c565b820191906000526020600020905b81548152906001019060200180831161080f57829003601f168201915b50505050600283015460039093015491926001600160a01b039081169216905084565b600061085a81610b7d565b61070d6000805160206148bf83398151915283610711565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606001805480602002602001604051908101604052809291908181526020016000905b828210156109bf57600084815260209081902060408051608081019091526004850290910180546001600160a01b03168252600181018054929391929184019161090890611092565b80601f016020809104026020016040519081016040528092919081815260200182805461093490611092565b80156109815780601f1061095657610100808354040283529160200191610981565b820191906000526020600020905b81548152906001019060200180831161096457829003601f168201915b505050918352505060028201546001600160a01b039081166020808401919091526003909301541660409091015290825260019290920191016108bf565b50505050905090565b600260205281600052604060002081815481106109e457600080fd5b6000918252602090912060049091020180546001820180546001600160a01b0390921694509192506107b390611092565b6001600160a01b0381166000908152600260209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610b4d57600084815260209081902060408051608081019091526004850290910180546001600160a01b031682526001810180549293919291840191610a9690611092565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac290611092565b8015610b0f5780601f10610ae457610100808354040283529160200191610b0f565b820191906000526020600020905b815481529060010190602001808311610af257829003601f168201915b505050918352505060028201546001600160a01b03908116602080840191909152600390930154166040909101529082526001929092019101610a4d565b505050509050919050565b600082815260208190526040902060010154610b7381610b7d565b6107368383610c1c565b610b878133610c87565b50565b6000610b968383610872565b610c14576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610bcc3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161029e565b50600061029e565b6000610c288383610872565b15610c14576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161029e565b610c918282610872565b61070d5760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b6136d2806111ed83390190565b600060208284031215610ce357600080fd5b81356001600160e01b031981168114610cfb57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610d2957600080fd5b813567ffffffffffffffff811115610d4357610d43610d02565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610d7257610d72610d02565b604052818152838201602001851015610d8a57600080fd5b816020850160208301376000918101602001919091529392505050565b80356001600160a01b0381168114610dbe57600080fd5b919050565b600080600080600060a08688031215610ddb57600080fd5b853567ffffffffffffffff811115610df257600080fd5b610dfe88828901610d18565b955050602086013567ffffffffffffffff811115610e1b57600080fd5b610e2788828901610d18565b945050610e3660408701610da7565b9250610e4460608701610da7565b9150608086013560ff81168114610e5a57600080fd5b809150509295509295909350565b600060208284031215610e7a57600080fd5b610cfb82610da7565b600060208284031215610e9557600080fd5b5035919050565b60008060408385031215610eaf57600080fd5b82359150610ebf60208401610da7565b90509250929050565b6000815180845260005b81811015610eee57602081850181015186830182015201610ed2565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152608060208201819052600090610f3290830186610ec8565b6001600160a01b039485166040840152929093166060909101529392505050565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610ff157868503603f19018452815180516001600160a01b03168652602080820151608091880182905290610fb690880182610ec8565b6040838101516001600160a01b03908116918a0191909152606093840151169290970191909152506020938401939190910190600101610f7b565b50929695505050505050565b6000806040838503121561101057600080fd5b61101983610da7565b946020939093013593505050565b60a08152600061103a60a0830188610ec8565b828103602084015261104c8188610ec8565b6001600160a01b0396871660408501529490951660608301525060ff919091166080909101529392505050565b60006020828403121561108b57600080fd5b5051919050565b600181811c908216806110a657607f821691505b6020821081036110c657634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561076f57806000526020600020601f840160051c810160208510156110f35750805b601f840160051c820191505b8181101561111357600081556001016110ff565b5050505050565b815167ffffffffffffffff81111561113457611134610d02565b611148816111428454611092565b846110cc565b6020601f82116001811461117c57600083156111645750848201515b600019600385901b1c1916600184901b178455611113565b600084815260208120601f198516915b828110156111ac578785015182556020948501946001909201910161118c565b50848210156111ca5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b602081526000610cfb6020830184610ec856fe608060405234801561001057600080fd5b506040516136d23803806136d283398101604081905261002f91610316565b6001805561003e600033610188565b506100697f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92933610188565b5060026100768682610444565b5060036100838582610444565b50600480546001600160a01b038086166001600160a01b03199283161790925560058054928516929091169190911790556100bf81600a6105ff565b60065560405160009030906100d390610234565b6100de929190610615565b604051809103906000f0801580156100fa573d6000803e3d6000fd5b50600a60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060013060405161013090610234565b61013b929190610615565b604051809103906000f080158015610157573d6000803e3d6000fd5b50600b80546001600160a01b0319166001600160a01b039290921691909117905550506001600c555061064f915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1661022a576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101e23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161022e565b5060005b92915050565b610c8380612a4f83390190565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261026857600080fd5b81516001600160401b0381111561028157610281610241565b604051601f8201601f19908116603f011681016001600160401b03811182821017156102af576102af610241565b6040528181528382016020018510156102c757600080fd5b60005b828110156102e6576020818601810151838301820152016102ca565b506000918101602001919091529392505050565b80516001600160a01b038116811461031157600080fd5b919050565b600080600080600060a0868803121561032e57600080fd5b85516001600160401b0381111561034457600080fd5b61035088828901610257565b602088015190965090506001600160401b0381111561036e57600080fd5b61037a88828901610257565b945050610389604087016102fa565b9250610397606087016102fa565b9150608086015160ff811681146103ad57600080fd5b809150509295509295909350565b600181811c908216806103cf57607f821691505b6020821081036103ef57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561043f57806000526020600020601f840160051c8101602085101561041c5750805b601f840160051c820191505b8181101561043c5760008155600101610428565b50505b505050565b81516001600160401b0381111561045d5761045d610241565b6104718161046b84546103bb565b846103f5565b6020601f8211600181146104a5576000831561048d5750848201515b600019600385901b1c1916600184901b17845561043c565b600084815260208120601f198516915b828110156104d557878501518255602094850194600190920191016104b5565b50848210156104f35786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b6001815b60018411156105535780850481111561053757610537610502565b600184161561054557908102905b60019390931c92800261051c565b935093915050565b60008261056a5750600161022e565b816105775750600061022e565b816001811461058d5760028114610597576105b3565b600191505061022e565b60ff8411156105a8576105a8610502565b50506001821b61022e565b5060208310610133831016604e8410600b84101617156105d6575081810a61022e565b6105e36000198484610518565b80600019048211156105f7576105f7610502565b029392505050565b600061060e60ff84168361055b565b9392505050565b604081016002841061063757634e487b7160e01b600052602160045260246000fd5b9281526001600160a01b039190911660209091015290565b6123f18061065e6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806375829def116100f9578063a266f85a11610097578063d547741f11610071578063d547741f14610430578063e6bfd26a14610443578063f0dff6b61461044b578063f5b541a61461045e57600080fd5b8063a266f85a146103ff578063c55dae6314610414578063cdcf4b9b1461042757600080fd5b806386f34467116100d357806386f34467146103be5780638c29c911146103d157806391d14854146103e4578063a217fddf146103f757600080fd5b806375829def146103905780637d4feb72146103a35780637ee68546146103b657600080fd5b80632c7d413b116101665780634622c218116101405780634622c21814610342578063514fcac7146103555780636e84a27114610368578063709bfe9a1461037057600080fd5b80632c7d413b146103075780632f2ff15d1461031a57806336568abe1461032f57600080fd5b806323edfa2e116101a257806323edfa2e1461023c578063248a9ca31461025d5780632a58b330146102805780632c4cb11a1461028957600080fd5b806301ffc9a7146101c9578063049405be146101f1578063217a4b7014610211575b600080fd5b6101dc6101d7366004611ce7565b610485565b60405190151581526020015b60405180910390f35b6102046101ff366004611d2d565b6104bc565b6040516101e89190611d82565b600554610224906001600160a01b031681565b6040516001600160a01b0390911681526020016101e8565b61024f61024a366004611e3a565b61066a565b6040519081526020016101e8565b61024f61026b366004611e5c565b60009081526020819052604090206001015490565b61024f600c5481565b6102f2610297366004611e5c565b60076020819052600091825260409091208054600182015460028301546003840154600485015460058601546006870154978701546008909701546001600160a01b039096169794969395929460ff92831694919390921689565b6040516101e899989796959493929190611e75565b61024f610315366004611e3a565b61069b565b61032d610328366004611ed6565b6106b7565b005b61032d61033d366004611ed6565b6106e2565b61032d610350366004611f11565b61071a565b61032d610363366004611e5c565b610aff565b61032d610b75565b61038361037e366004611d2d565b610c4e565b6040516101e89190611f4a565b61032d61039e366004611d2d565b610ddd565b61032d6103b136600461205a565b610e55565b61032d610e8b565b600b54610224906001600160a01b031681565b61032d6103df36600461208f565b6111dc565b6101dc6103f2366004611ed6565b6112ca565b61024f600081565b6104076112f3565b6040516101e891906121af565b600454610224906001600160a01b031681565b61024f60065481565b61032d61043e366004611ed6565b611381565b6104076113a6565b600a54610224906001600160a01b031681565b61024f7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92981565b60006001600160e01b03198216637965db0b60e01b14806104b657506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060006104c983610c4e565b90506000815167ffffffffffffffff8111156104e7576104e7611f82565b60405190808252806020026020018201604052801561052057816020015b61050d611c71565b8152602001906001900390816105055790505b50905060005b82518110156106625760076000848381518110610545576105456121fd565b60200260200101518152602001908152602001600020604051806101200160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff1660018111156105d8576105d8611d48565b60018111156105e9576105e9611d48565b815260058281015460208301526006830154604083015260078301546060830152600883015460809092019160ff169081111561062857610628611d48565b600581111561063957610639611d48565b8152505082828151811061064f5761064f6121fd565b6020908102919091010152600101610526565b509392505050565b6009602052816000526040600020818154811061068657600080fd5b90600052602060002001600091509150505481565b6008602052816000526040600020818154811061068657600080fd5b6000828152602081905260409020600101546106d2816113b3565b6106dc83836113bd565b50505050565b6001600160a01b038116331461070b5760405163334bd91960e11b815260040160405180910390fd5b610715828261144f565b505050565b600061072983856006546114ba565b9050600081116107955760405162461bcd60e51b815260206004820152602c60248201527f51756f746520746f6b656e20616d6f756e74206d75737420626520677265617460448201526b6572207468616e207a65726f60a01b60648201526084015b60405180910390fd5b6107a1338486886114d1565b6107e25760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b604482015260640161078c565b600083116108325760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015260640161078c565b600061083e4384612229565b90506000604051806101200160405280336001600160a01b0316815260200187815260200186815260200186815260200188600181111561088157610881611d48565b8152600c5460208201524360408201526060810184905260800160019052905060008760018111156108b5576108b5611d48565b03610943576000868152600860209081526040808320600c5481546001810183559185529290932090920155600a5490516390b5561d60e01b8152600481018890526001600160a01b03909116906390b5561d90602401600060405180830381600087803b15801561092657600080fd5b505af115801561093a573d6000803e3d6000fd5b505050506109c8565b6000868152600960209081526040808320600c5481546001810183559185529290932090920155600b5490516390b5561d60e01b8152600481018890526001600160a01b03909116906390b5561d90602401600060405180830381600087803b1580156109af57600080fd5b505af11580156109c3573d6000803e3d6000fd5b505050505b600c54600090815260076020908152604091829020835181546001600160a01b0319166001600160a01b0390911617815590830151600180830191909155918301516002820155606083015160038201556080830151600482018054859460ff19909116908381811115610a3e57610a3e611d48565b021790555060a0820151816005015560c0820151816006015560e082015181600701556101008201518160080160006101000a81548160ff02191690836005811115610a8c57610a8c611d48565b02179055509050507fc61479f640c5df729563b3ae73c6592bfaef0f2f68133af5b287fc6bc1635cf5600c54338888898c60016000438b604051610ad99a9998979695949392919061224c565b60405180910390a1600c8054906000610af1836122b9565b919050555050505050505050565b600081815260076020526040902080546001600160a01b03163314610b665760405162461bcd60e51b815260206004820152601960248201527f596f7520646f206e6f74206f776e2074686973206f7264657200000000000000604482015260640161078c565b610b718260036115f7565b5050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b929610b9f816113b3565b60015b600c54811015610b715760008181526007602052604090206001600882015460ff166005811115610bd557610bd5611d48565b03610c45578060070154431115610bf657610bf18260046115f7565b610c45565b8054600382015460018301546004840154610c1f936001600160a01b031692919060ff166114d1565b610c2e57610bf18260056115f7565b8060030154600003610c4557610c458260026115f7565b50600101610ba2565b6060600080600c5467ffffffffffffffff811115610c6e57610c6e611f82565b604051908082528060200260200182016040528015610c97578160200160208202803683370190505b50905060015b600c54811015610d425760008181526007602052604090206001600882015460ff166005811115610cd057610cd0611d48565b148015610ce1575080600701544311155b15610d39576001600160a01b0386161580610d08575080546001600160a01b038781169116145b15610d395781838581518110610d2057610d206121fd565b602090810291909101015283610d35816122b9565b9450505b50600101610c9d565b5060008267ffffffffffffffff811115610d5e57610d5e611f82565b604051908082528060200260200182016040528015610d87578160200160208202803683370190505b50905060005b83811015610dd457828181518110610da757610da76121fd565b6020026020010151828281518110610dc157610dc16121fd565b6020908102919091010152600101610d8d565b50949350505050565b6000610de8816113b3565b6001600160a01b038216610e3e5760405162461bcd60e51b815260206004820181905260248201527f4e65772061646d696e20616464726573732063616e6e6f74206265207a65726f604482015260640161078c565b610e496000836113bd565b5061071560003361144f565b60005b8151811015610b7157610e83828281518110610e7657610e766121fd565b6020026020010151610aff565b600101610e58565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b929610eb5816113b3565b610ebd610b75565b600a5460408051635ca1e16560e01b815290516000926001600160a01b031691635ca1e1659160048083019260209291908290030181865afa158015610f07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2b91906122d2565b90506000600b60009054906101000a90046001600160a01b03166001600160a01b0316635ca1e1656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa691906122d2565b9050600082118015610fb85750600081115b8015610fc45750818110155b15610715576000828152600860205260408120610fe0906117d2565b600083815260096020526040812091925090610ffb906117d2565b90506110068261183f565b61108d57600a60009054906101000a90046001600160a01b03166001600160a01b0316633351cc736040518163ffffffff1660e01b81526004016020604051808303816000875af115801561105f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108391906122d2565b5050505050610ebd565b6110968161183f565b6110ef57600b60009054906101000a90046001600160a01b03166001600160a01b0316633351cc736040518163ffffffff1660e01b81526004016020604051808303816000875af115801561105f573d6000803e3d6000fd5b600082815260076020526040808220838352908220600380830154908201549293919290918183106111215781611123565b825b905061112f8582611870565b6111398482611870565b84548454600187015461115b926001600160a01b03908116921690849061191d565b84548454600187015460058089015490880154604080516001600160a01b0396871681529590941660208601528484019290925260608401859052608084015260a0830152517f532c61a7371ced9ca44dc5bb81f73a24cb3d0af8f4396a3d03c3db699be662939181900360c00190a1505050505050505050610ebd565b50565b82518451146111fd5760405162461bcd60e51b815260040161078c906122eb565b815183511461121e5760405162461bcd60e51b815260040161078c906122eb565b805182511461123f5760405162461bcd60e51b815260040161078c906122eb565b60005b84518110156112c3576112bb858281518110611260576112606121fd565b602002602001015185838151811061127a5761127a6121fd565b6020026020010151858481518110611294576112946121fd565b60200260200101518585815181106112ae576112ae6121fd565b602002602001015161071a565b600101611242565b5050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6003805461130090612320565b80601f016020809104026020016040519081016040528092919081815260200182805461132c90612320565b80156113795780601f1061134e57610100808354040283529160200191611379565b820191906000526020600020905b81548152906001019060200180831161135c57829003601f168201915b505050505081565b60008281526020819052604090206001015461139c816113b3565b6106dc838361144f565b6002805461130090612320565b6111d98133611b74565b60006113c983836112ca565b611447576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556113ff3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016104b6565b5060006104b6565b600061145b83836112ca565b15611447576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016104b6565b60006114c7848484611bad565b90505b9392505050565b6000808260018111156114e6576114e6611d48565b036115775760006114fa85856006546114ba565b6005546040516370a0823160e01b81526001600160a01b0389811660048301529293508392909116906370a0823190602401602060405180830381865afa158015611549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156d91906122d2565b10159150506115ef565b600480546040516370a0823160e01b81526001600160a01b03888116938201939093528692909116906370a0823190602401602060405180830381865afa1580156115c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ea91906122d2565b101590505b949350505050565b60008281526007602052604090206001600882015460ff16600581111561162057611620611d48565b1461162a57505050565b600080600483015460ff16600181111561164657611646611d48565b146116635760018201546000908152600960205260409020611677565b600182015460009081526008602052604090205b905060005b81548110156117265784828281548110611698576116986121fd565b90600052602060002001540361171e57815482906116b89060019061235a565b815481106116c8576116c86121fd565b90600052602060002001548282815481106116e5576116e56121fd565b9060005260206000200181905550818054806117035761170361236d565b60019003818190600052602060002001600090559055611726565b60010161167c565b5060088201805484919060ff1916600183600581111561174857611748611d48565b0217905550600582015482546001840154600285015460048601546008870154600688015460078901546040517fc61479f640c5df729563b3ae73c6592bfaef0f2f68133af5b287fc6bc1635cf5986117c49890976001600160a01b03909116969095909460009460ff9283169492909116926003929061224c565b60405180910390a150505050565b6000805b8254811015611836576118048382815481106117f4576117f46121fd565b906000526020600020015461183f565b1561182e5782818154811061181b5761181b6121fd565b9060005260206000200154915050919050565b6001016117d6565b50600092915050565b6000600160008381526007602052604090206008015460ff16600581111561186957611869611d48565b1492915050565b80826003016000828254611884919061235a565b909155505060038201546000036118a457610b71826005015460026115f7565b60058201548254600180850154600286015460038701546004880154600689015460078a01546040517fc61479f640c5df729563b3ae73c6592bfaef0f2f68133af5b287fc6bc1635cf5996119119990986001600160a01b039091169796959460ff16939092839261224c565b60405180910390a15050565b6001600160a01b03841661196b5760405162461bcd60e51b8152602060048201526015602482015274496e76616c69642061736b6572206164647265737360581b604482015260640161078c565b6001600160a01b0383166119ba5760405162461bcd60e51b8152602060048201526016602482015275496e76616c696420626964646572206164647265737360501b604482015260640161078c565b60008211611a0a5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015260640161078c565b60008111611a5a5760405162461bcd60e51b815260206004820152601f60248201527f5072696365206d7573742062652067726561746572207468616e207a65726f00604482015260640161078c565b6000611a6983836006546114ba565b6005546040516323b872dd60e01b81526001600160a01b0387811660048301528881166024830152604482018490529293509116906323b872dd906064016020604051808303816000875af1158015611ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aea9190612383565b50600480546040516323b872dd60e01b81526001600160a01b03888116938201939093528683166024820152604481018690529116906323b872dd906064016020604051808303816000875af1158015611b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6c9190612383565b505050505050565b611b7e82826112ca565b610b715760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161078c565b6000838302816000198587098281108382030391505080600003611be457838281611bda57611bda6123a5565b04925050506114ca565b808411611c045760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b60405180610120016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160006001811115611cb557611cb5611d48565b815260200160008152602001600081526020016000815260200160006005811115611ce257611ce2611d48565b905290565b600060208284031215611cf957600080fd5b81356001600160e01b0319811681146114ca57600080fd5b80356001600160a01b0381168114611d2857600080fd5b919050565b600060208284031215611d3f57600080fd5b6114ca82611d11565b634e487b7160e01b600052602160045260246000fd5b60028110611d6e57611d6e611d48565b9052565b60068110611d6e57611d6e611d48565b602080825282518282018190526000918401906040840190835b81811015611e2f57835160018060a01b0381511684526020810151602085015260408101516040850152606081015160608501526080810151611de26080860182611d5e565b5060a081015160a085015260c081015160c085015260e081015160e08501526101008101519050611e17610100850182611d72565b50602093909301926101209290920191600101611d9c565b509095945050505050565b60008060408385031215611e4d57600080fd5b50508035926020909101359150565b600060208284031215611e6e57600080fd5b5035919050565b6001600160a01b038a1681526020810189905260408101889052606081018790526101208101611ea86080830188611d5e565b8560a08301528460c08301528360e0830152611ec8610100830184611d72565b9a9950505050505050505050565b60008060408385031215611ee957600080fd5b82359150611ef960208401611d11565b90509250929050565b803560028110611d2857600080fd5b60008060008060808587031215611f2757600080fd5b611f3085611f02565b966020860135965060408601359560600135945092505050565b602080825282518282018190526000918401906040840190835b81811015611e2f578351835260209384019390920191600101611f64565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611fc157611fc1611f82565b604052919050565b600067ffffffffffffffff821115611fe357611fe3611f82565b5060051b60200190565b600082601f830112611ffe57600080fd5b813561201161200c82611fc9565b611f98565b8082825260208201915060208360051b86010192508583111561203357600080fd5b602085015b83811015612050578035835260209283019201612038565b5095945050505050565b60006020828403121561206c57600080fd5b813567ffffffffffffffff81111561208357600080fd5b6115ef84828501611fed565b600080600080608085870312156120a557600080fd5b843567ffffffffffffffff8111156120bc57600080fd5b8501601f810187136120cd57600080fd5b80356120db61200c82611fc9565b8082825260208201915060208360051b8501019250898311156120fd57600080fd5b6020840193505b828410156121265761211584611f02565b825260209384019390910190612104565b9650505050602085013567ffffffffffffffff81111561214557600080fd5b61215187828801611fed565b935050604085013567ffffffffffffffff81111561216e57600080fd5b61217a87828801611fed565b925050606085013567ffffffffffffffff81111561219757600080fd5b6121a387828801611fed565b91505092959194509250565b602081526000825180602084015260005b818110156121dd57602081860181015160408684010152016121c0565b506000604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156104b6576104b6612213565b60048110611d6e57611d6e611d48565b8a81526001600160a01b038a166020820152604081018990526060810188905260808101879052610140810161228560a0830188611d5e565b61229260c0830187611d72565b61229f60e083018661223c565b610100820193909352610120015298975050505050505050565b6000600182016122cb576122cb612213565b5060010190565b6000602082840312156122e457600080fd5b5051919050565b6020808252818101527f417272617973206d7573742068617665207468652073616d65206c656e677468604082015260600190565b600181811c9082168061233457607f821691505b60208210810361235457634e487b7160e01b600052602260045260246000fd5b50919050565b818103818111156104b6576104b6612213565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561239557600080fd5b815180151581146114ca57600080fd5b634e487b7160e01b600052601260045260246000fdfea264697066735822122088b5fc18d7905a867f376b7377a2f9326d41872063d7ca4c5337c4fa85952b4264736f6c634300081b0033608060405234801561001057600080fd5b50604051610c83380380610c8383398101604081905261002f91610163565b60018054808201825560008281527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69091015560028054849260ff19909116908381811115610080576100806101ad565b02179055506100af7f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f826100b7565b5050506101c3565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16610159576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101113390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161015d565b5060005b92915050565b6000806040838503121561017657600080fd5b82516002811061018557600080fd5b60208401519092506001600160a01b03811681146101a257600080fd5b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b610ab1806101d26000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80633e27ec9b1161008c57806390b5561d1161006657806390b5561d146101e957806391d14854146101fc578063a217fddf1461020f578063d547741f1461021757600080fd5b80633e27ec9b146101a55780635ca1e165146101cc57806372394ba6146101d457600080fd5b80632e1a49cc116100c85780632e1a49cc1461015b5780632f2ff15d146101755780633351cc731461018a57806336568abe1461019257600080fd5b806301ffc9a7146100ef5780631c01f29214610117578063248a9ca314610138575b600080fd5b6101026100fd3660046108da565b61022a565b60405190151581526020015b60405180910390f35b61012a610125366004610904565b610261565b60405190815260200161010e565b61012a610146366004610904565b60009081526020819052604090206001015490565b6002546101689060ff1681565b60405161010e9190610933565b61018861018336600461095b565b610282565b005b61012a6102ad565b6101886101a036600461095b565b6104fd565b61012a7f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f81565b61012a610535565b6101dc61056b565b60405161010e9190610997565b6101886101f7366004610904565b6105c3565b61010261020a36600461095b565b61070f565b61012a600081565b61018861022536600461095b565b610738565b60006001600160e01b03198216637965db0b60e01b148061025b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6001818154811061027157600080fd5b600091825260209091200154905081565b60008281526020819052604090206001015461029d8161075d565b6102a7838361076a565b50505050565b60007f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f6102d98161075d565b60018054116102e757600080fd5b6000600180815481106102fc576102fc6109da565b90600052602060002001549050600180808054905061031b9190610a06565b8154811061032b5761032b6109da565b906000526020600020015460018081548110610349576103496109da565b600091825260209091200155600180548061036657610366610a19565b600190038181906000526020600020016000905590556000600190505b600180546103919190610a06565b61039c826002610a2f565b10156104f65760006103af826002610a2f565b90506000600182815481106103c6576103c66109da565b6000918252602082200154915060016103df8482610a46565b815481106103ef576103ef6109da565b9060005260206000200154905061040682826107fc565b61041857610415836001610a46565b92505b61045c6001858154811061042e5761042e6109da565b90600052602060002001546001858154811061044c5761044c6109da565b90600052602060002001546107fc565b15610469575050506104f6565b6001838154811061047c5761047c6109da565b90600052602060002001546001858154811061049a5761049a6109da565b9060005260206000200154600186815481106104b8576104b86109da565b906000526020600020016000600187815481106104d7576104d76109da565b6000918252602090912001929092559190915550919250610383915050565b5091505090565b6001600160a01b03811633146105265760405163334bd91960e11b815260040160405180910390fd5b610530828261082e565b505050565b6001805460009110156105655760018081548110610555576105556109da565b9060005260206000200154905090565b50600090565b606060018054806020026020016040519081016040528092919081815260200182805480156105b957602002820191906000526020600020905b8154815260200190600101908083116105a5575b5050505050905090565b7f395f08be531c0d7403cba7c5ffd2b57329184452bcebcd6a48299ebbbf39db6f6105ed8161075d565b60018054808201825560008281527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69091018490558154909161062f91610a06565b90505b60018111801561067d575061067b600161064d600284610a59565b8154811061065d5761065d6109da565b90600052602060002001546001838154811061044c5761044c6109da565b155b1561053057826001610690600284610a59565b815481106106a0576106a06109da565b906000526020600020015460016002846106ba9190610a59565b815481106106ca576106ca6109da565b906000526020600020016000600185815481106106e9576106e96109da565b6000918252602090912001929092559190915550610708600282610a59565b9050610632565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6000828152602081905260409020600101546107538161075d565b6102a7838361082e565b6107678133610899565b50565b6000610776838361070f565b6107f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556107ac3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161025b565b50600061025b565b60008060025460ff1660018111156108165761081661091d565b1461082357818311610827565b8183105b9392505050565b600061083a838361070f565b156107f4576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161025b565b6108a3828261070f565b6108d65760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b5050565b6000602082840312156108ec57600080fd5b81356001600160e01b03198116811461082757600080fd5b60006020828403121561091657600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b602081016002831061095557634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561096e57600080fd5b8235915060208301356001600160a01b038116811461098c57600080fd5b809150509250929050565b602080825282518282018190526000918401906040840190835b818110156109cf5783518352602093840193909201916001016109b1565b509095945050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561025b5761025b6109f0565b634e487b7160e01b600052603160045260246000fd5b808202811582820484141761025b5761025b6109f0565b8082018082111561025b5761025b6109f0565b600082610a7657634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212206f7843179fb6f52f6420bc6cb1a4400b62604b6fb8eee8951082630b31da04c264736f6c634300081b0033a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a264697066735822122078689d7b24144eda2b806ee00828a83bef33bb19de57809bf53ee2610d537e3f64736f6c634300081b0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.