Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- UFCFight
- Optimization enabled
- true
- Compiler version
- v0.8.20+commit.a1b79de6
- Optimization runs
- 200
- EVM Version
- paris
- Verified at
- 2025-03-07T03:55:04.176218Z
contracts/UFC/UFCFight.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { SwapperUpgradeable } from "../library/SwapperUpgradeable.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IUFC } from "../interfaces/IUFC.sol";
contract UFCFight is OwnableUpgradeable, SwapperUpgradeable {
enum RoundStatus {
WAITING,
STARTED,
CLOSED,
FINISHING,
FINISHED,
CANCELING,
CANCELLED
}
struct Bet {
address player;
uint256 entryId;
uint256 amount;
uint256 timestamp;
}
struct Round {
uint256 roundID;
string player1Name;
string player2Name;
uint256 feeAmount;
uint256 player1TotalAmount;
uint256 player2TotalAmount;
Bet[] player1Bets;
Bet[] player2Bets;
uint48 closeAt;
uint32 player1LastIndex;
uint32 player2LastIndex;
uint8 result; // 0: player1, 1: player2, 2: draw
RoundStatus status;
}
IUFC public ufc;
IERC20 public pspn;
Round[] public rounds;
uint256 public roundIds;
uint256 public entryIds;
uint256 public chunkSize;
/* Admin */
mapping(address => bool) public isAdmin;
event RoundStarted(uint256 roundId, uint256 closeAt, uint256 timestamp);
event EnteredRound(uint256 roundId, uint256 entryId, address player, uint256 amount, uint256 expectation, uint256 timestamp);
event RoundFinished(uint256 roundId, uint8 result, string winner, uint256 totalAmount, uint256 feeAmount, uint256 pspnAmount, uint256 timestamp);
event FeeTaken(uint256 roundId, uint256 ufcAmount, uint256 pspnAmount, uint256 timestamp);
function initialize(address ufcAddress, address pspnAddress, address _routerAddress, address _usdtAddress) external initializer {
ufc = IUFC(ufcAddress);
pspn = IERC20(pspnAddress);
isAdmin[msg.sender] = true;
chunkSize = 100;
__Ownable_init(msg.sender);
__Swapper_init(_routerAddress, _usdtAddress);
}
modifier onlyAdmin() {
require(isAdmin[msg.sender] == true, "only admin");
_;
}
modifier excludeContract() {
require(msg.sender == tx.origin, "contract not allowed");
_;
}
function createRound(string memory player1Name, string memory player2Name, uint256 closeAt) external onlyAdmin {
rounds.push();
Round storage roundInfo = rounds[roundIds];
roundInfo.roundID = roundIds;
roundInfo.player1Name = player1Name;
roundInfo.player2Name = player2Name;
roundInfo.closeAt = uint48(closeAt);
roundInfo.status = RoundStatus.STARTED;
emit RoundStarted(roundIds, closeAt, block.timestamp);
roundIds ++;
}
function enterRound(uint256 roundId, uint256 amount, uint256 expectation) external payable excludeContract {
Round storage roundInfo = rounds[roundId];
require(roundId < roundIds, "invalid round id");
require(roundInfo.status == RoundStatus.STARTED, "cannot enter");
require(roundInfo.closeAt > block.timestamp, "bet closed");
require(expectation < 2, "invalid expectation");
require(amount > 0, "invalid usdAmount");
uint256 newBetId;
if (expectation == 0) {
// player1
newBetId = roundInfo.player1Bets.length;
roundInfo.player1Bets.push();
roundInfo.player1TotalAmount += amount;
} else {
newBetId = roundInfo.player2Bets.length;
roundInfo.player2Bets.push();
roundInfo.player2TotalAmount += amount;
}
Bet storage betInfo = expectation == 0 ? roundInfo.player1Bets[newBetId] : roundInfo.player2Bets[newBetId];
betInfo.player = msg.sender;
betInfo.entryId = entryIds;
betInfo.amount = amount;
betInfo.timestamp = block.timestamp;
ufc.transferFrom(msg.sender, address(this), amount);
emit EnteredRound(roundId, entryIds, msg.sender, amount, expectation, block.timestamp);
entryIds++;
}
function finishRound(uint256 roundId, uint8 result) external onlyAdmin excludeContract {
Round storage roundInfo = rounds[roundId];
bool isClosed = (roundInfo.status == RoundStatus.STARTED && roundInfo.closeAt <= block.timestamp) || roundInfo.status == RoundStatus.CLOSED;
require(roundId < roundIds, "invalid round id");
require(isClosed || roundInfo.status == RoundStatus.FINISHING, "cannot finish");
// Take Fees and send rewards
if (roundInfo.status != RoundStatus.FINISHING) {
string memory winnerName = result == 0 ? roundInfo.player1Name : roundInfo.player2Name;
uint256 totalAmount = roundInfo.player1TotalAmount + roundInfo.player1TotalAmount;
uint256 feeAmount = (totalAmount * 3) / 100;
uint256 pspnAmount = _takeFees(roundId, feeAmount);
roundInfo.status = RoundStatus.FINISHING;
roundInfo.result = result;
roundInfo.feeAmount = feeAmount;
emit RoundFinished(roundId, result, winnerName, totalAmount, feeAmount, pspnAmount, block.timestamp);
}
bool isFinished = _sendReward(roundId);
if (isFinished) {
roundInfo.status = RoundStatus.FINISHED;
}
}
function _sendReward(uint256 roundId) internal returns (bool) {
Round storage roundInfo = rounds[roundId];
uint8 result = roundInfo.result;
if (result < 2) {
// Not draw case
Bet[] storage bets = result == 0 ? roundInfo.player1Bets : roundInfo.player2Bets;
uint256 winnerTotalAmount = result == 0 ? roundInfo.player1TotalAmount : roundInfo.player2TotalAmount;
uint256 totalAmount = ((roundInfo.player1TotalAmount + roundInfo.player2TotalAmount) * 97) / 100;
uint32 lastIndex = result == 0 ? roundInfo.player1LastIndex : roundInfo.player2LastIndex;
uint256 length = bets.length;
uint32 i;
for (i = 0; i + lastIndex < length && i < chunkSize; i++) {
uint256 reward = (bets[i + lastIndex].amount * totalAmount) / winnerTotalAmount;
ufc.transfer(bets[i + lastIndex].player, reward);
}
if (result == 0) roundInfo.player1LastIndex = i + lastIndex;
else roundInfo.player2LastIndex = i + lastIndex;
if (i + lastIndex == length) {
return true;
}
} else {
// Draw case
if (roundInfo.player1LastIndex < roundInfo.player1Bets.length) {
Bet[] storage bets = roundInfo.player1Bets;
uint32 lastIndex = roundInfo.player1LastIndex;
uint256 length = roundInfo.player1Bets.length;
uint32 i;
for (i = 0; i + lastIndex < length && i < chunkSize; i++) {
uint256 reward = (bets[i + lastIndex].amount * 97) / 100;
ufc.transfer(bets[i + lastIndex].player, reward);
}
roundInfo.player1LastIndex = i + lastIndex;
} else if (roundInfo.player2LastIndex < roundInfo.player2Bets.length) {
Bet[] storage bets = roundInfo.player2Bets;
uint32 lastIndex = roundInfo.player2LastIndex;
uint256 length = roundInfo.player2Bets.length;
uint32 i;
for (i = 0; i + lastIndex < length && i < chunkSize; i++) {
uint256 reward = (bets[i + lastIndex].amount * 97) / 100;
ufc.transfer(bets[i + lastIndex].player, reward);
}
roundInfo.player2LastIndex = i + lastIndex;
if (i + lastIndex == length) {
return true;
}
} else {
return true;
}
}
return false;
}
function _takeFees(uint256 roundId, uint256 feeAmount) internal returns (uint256 pspnAmount) {
if (feeAmount == 0) return 0;
pspnAmount = _swap(address(ufc), address(pspn), feeAmount, address(ufc));
emit FeeTaken(roundId, feeAmount, pspnAmount, block.timestamp);
}
function getRounds() external view returns (Round[] memory) {
return rounds;
}
function setAdmin(address addr, bool value) external onlyOwner {
isAdmin[addr] = value;
}
function getRound(uint256 id) external view returns (Round memory) {
return rounds[id];
}
}
@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable
struct OwnableStorage {
address _owner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
assembly {
$.slot := OwnableStorageLocation
}
}
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
OwnableStorage storage $ = _getOwnableStorage();
return $._owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
OwnableStorage storage $ = _getOwnableStorage();
address oldOwner = $._owner;
$._owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}
@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
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;
}
}
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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);
}
contracts/interfaces/IPRC20.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.7;
interface IPRC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function decimals() external view returns (uint8);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contracts/interfaces/IPulseXRouter.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.2;
interface IPulseXRouter01 {
function factory() external pure returns (address);
function WPLS() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function swapTokensForExactETH(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapETHForExactTokens(
uint amountOut,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
interface IPulseXRouter02 is IPulseXRouter01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
contracts/interfaces/IUFC.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.7;
interface IUFC {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function decimals() external view returns (uint8);
function sellTax() external view returns (uint256);
function buyTax() external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contracts/library/SwapperUpgradeable.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.7;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "../interfaces/IPulseXRouter.sol";
import "../interfaces/IPRC20.sol";
abstract contract SwapperUpgradeable is Initializable {
IPulseXRouter02 public router;
mapping(address => bool) public isTokenStable;
address public usdtAddress;
/**
* @dev Initializes the contract router and usdtAddress
*/
function __Swapper_init(address _routerAddress, address _usdtAddress) internal onlyInitializing {
__Swapper_init_unchained(_routerAddress, _usdtAddress);
}
function __Swapper_init_unchained(address _routerAddress, address _usdtAddress) internal onlyInitializing {
router = IPulseXRouter02(_routerAddress);
usdtAddress = _usdtAddress;
}
function setTokenStable(address addr, bool value) internal {
isTokenStable[addr] = value;
}
function getTokenPrice(address tokenAddress, uint256 decimal) public view returns (uint256) {
uint8 usdtDecimals = IPRC20(usdtAddress).decimals();
if (isTokenStable[tokenAddress]) return 10 ** 18;
uint256 tokenAmount = 1;
if (
tokenAddress == 0x8D36123903f504eB81eEB832727af517c0db26bD ||
tokenAddress == 0xa27aDe5806Ded801b93499C6fA23cc8dC9AC55EA
) {
tokenAmount = 100000;
}
(, , uint256 maxAmountOut) = _getOptimizedAmountOut(tokenAddress, usdtAddress, tokenAmount * 10 ** decimal);
return (maxAmountOut * 10 ** (18 - usdtDecimals)) / tokenAmount;
}
function _swap(
address tokenFrom,
address tokenTo,
uint256 amount,
address receiver
) internal returns (uint256 outputAmount) {
if (amount == 0) return outputAmount;
if (tokenFrom == tokenTo) {
if (address(this) != receiver) {
if (tokenFrom == address(0)) {
payable(receiver).transfer(amount);
} else {
IPRC20(tokenFrom).transfer(receiver, amount);
}
}
return amount;
}
(IPulseXRouter02 optimalRouter, address[] memory path, uint256 maxAmountOut) = _getOptimizedAmountOut(
tokenFrom,
tokenTo,
amount
);
outputAmount = _swapWithRouterParams(tokenFrom, tokenTo, amount, receiver, optimalRouter, path);
}
function _swapWithRouterParams(
address tokenFrom,
address tokenTo,
uint256 amount,
address receiver,
IPulseXRouter02 optimalRouter,
address[] memory path
) internal returns (uint256 outputAmount) {
address nineInchRouterAddress = 0xeB45a3c4aedd0F47F345fB4c8A1802BB5740d725;
if (tokenTo != address(0)) {
uint256 prevBalance = IPRC20(tokenTo).balanceOf(receiver);
if (tokenFrom == address(0)) {
optimalRouter.swapExactETHForTokens{ value: amount }(0, path, receiver, block.timestamp);
} else if (tokenFrom == router.WPLS()) {
IPRC20(tokenFrom).approve(address(optimalRouter), amount);
optimalRouter.swapExactTokensForTokens(amount, 0, path, receiver, block.timestamp);
} else {
IPRC20(tokenFrom).approve(address(optimalRouter), amount);
if (address(optimalRouter) != nineInchRouterAddress) {
optimalRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amount,
0,
path,
receiver,
block.timestamp
);
} else {
optimalRouter.swapExactTokensForTokens(amount, 0, path, receiver, block.timestamp);
}
}
uint256 afterBalance = IPRC20(tokenTo).balanceOf(receiver);
outputAmount = afterBalance - prevBalance;
} else {
IPRC20(tokenFrom).approve(address(optimalRouter), amount);
uint256 prevBalance = receiver.balance;
optimalRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(amount, 0, path, receiver, block.timestamp);
uint256 afterBalance = receiver.balance;
outputAmount = afterBalance - prevBalance;
}
}
function _getPossiblePaths(
address tokenFrom,
address tokenTo
) public view returns (address[] memory pulseXPath, address[] memory nineInchPath) {
address nineInchTokenAddress = 0x3ca80d83277e721171284667829c686527B8b3c5;
address wplsAddress = router.WPLS();
if (tokenTo != wplsAddress && tokenTo != address(0)) {
if (tokenFrom == address(0) || tokenFrom == wplsAddress) {
pulseXPath = new address[](2);
pulseXPath[0] = wplsAddress;
pulseXPath[1] = tokenTo;
nineInchPath = new address[](3);
nineInchPath[0] = wplsAddress;
nineInchPath[1] = nineInchTokenAddress;
nineInchPath[2] = tokenTo;
} else if (tokenFrom == nineInchTokenAddress) {
pulseXPath = new address[](3);
pulseXPath[0] = tokenFrom;
pulseXPath[1] = wplsAddress;
pulseXPath[2] = tokenTo;
nineInchPath = new address[](2);
nineInchPath[0] = nineInchTokenAddress;
nineInchPath[1] = tokenTo;
} else {
pulseXPath = new address[](3);
pulseXPath[0] = tokenFrom;
pulseXPath[1] = wplsAddress;
pulseXPath[2] = tokenTo;
nineInchPath = new address[](3);
nineInchPath[0] = tokenFrom;
nineInchPath[1] = nineInchTokenAddress;
nineInchPath[2] = tokenTo;
}
} else {
if (tokenFrom == nineInchTokenAddress) {
pulseXPath = new address[](2);
pulseXPath[0] = tokenFrom;
pulseXPath[1] = wplsAddress;
nineInchPath = new address[](2);
nineInchPath[0] = nineInchTokenAddress;
nineInchPath[1] = wplsAddress;
} else {
pulseXPath = new address[](2);
pulseXPath[0] = tokenFrom;
pulseXPath[1] = wplsAddress;
nineInchPath = new address[](3);
nineInchPath[0] = tokenFrom;
nineInchPath[1] = nineInchTokenAddress;
nineInchPath[2] = tokenTo;
}
}
}
function _getAmountOutWithoutException(
IPulseXRouter02 router,
address[] memory path,
uint256 amountIn
) public view returns (uint256) {
try router.getAmountsOut(amountIn, path) returns (uint256[] memory amounts) {
return amounts[amounts.length - 1];
} catch Error(string memory reason) {
return 0;
} catch (bytes memory reason) {
return 0;
}
}
function _getAmountInWithoutException(
IPulseXRouter02 router,
address[] memory path,
uint256 amountOut
) public view returns (uint256) {
try router.getAmountsIn(amountOut, path) returns (uint256[] memory amounts) {
return amounts[0];
} catch Error(string memory reason) {
return 0;
} catch (bytes memory reason) {
return 0;
}
}
function _getOptimizedAmountOut(
address tokenFrom,
address tokenTo,
uint256 amountIn
) public view returns (IPulseXRouter02 router, address[] memory path, uint256 maxAmountOut) {
IPulseXRouter02 routerV1 = IPulseXRouter02(0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02);
IPulseXRouter02 routerV2 = IPulseXRouter02(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
IPulseXRouter02 nineInchRouter = IPulseXRouter02(0xeB45a3c4aedd0F47F345fB4c8A1802BB5740d725);
(address[] memory pulseXPath, address[] memory nineInchPath) = _getPossiblePaths(tokenFrom, tokenTo);
uint256 v1AmountOut = _getAmountOutWithoutException(routerV1, pulseXPath, amountIn);
uint256 v2AmountOut = _getAmountOutWithoutException(routerV2, pulseXPath, amountIn);
uint256 nineInchAmountOut = _getAmountOutWithoutException(nineInchRouter, nineInchPath, amountIn);
if (v1AmountOut != 0 && v1AmountOut > maxAmountOut) {
router = routerV1;
path = pulseXPath;
maxAmountOut = v1AmountOut;
}
if (v2AmountOut != 0 && v2AmountOut > maxAmountOut) {
router = routerV2;
path = pulseXPath;
maxAmountOut = v2AmountOut;
}
if (nineInchAmountOut != 0 && nineInchAmountOut > maxAmountOut) {
router = nineInchRouter;
path = nineInchPath;
maxAmountOut = nineInchAmountOut;
}
}
function _getOptimizedAmountIn(
address tokenFrom,
address tokenTo,
uint256 amountOut
) public view returns (IPulseXRouter02 router, address[] memory path, uint256 minAmountIn) {
IPulseXRouter02 routerV1 = IPulseXRouter02(0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02);
IPulseXRouter02 routerV2 = IPulseXRouter02(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
IPulseXRouter02 nineInchRouter = IPulseXRouter02(0xeB45a3c4aedd0F47F345fB4c8A1802BB5740d725);
(address[] memory pulseXPath, address[] memory nineInchPath) = _getPossiblePaths(tokenFrom, tokenTo);
uint256 v1AmountIn = _getAmountInWithoutException(routerV1, pulseXPath, amountOut);
uint256 v2AmountIn = _getAmountInWithoutException(routerV2, pulseXPath, amountOut);
uint256 nineInchAmountIn = _getAmountInWithoutException(nineInchRouter, nineInchPath, amountOut);
if (v1AmountIn != 0 && (minAmountIn == 0 || v1AmountIn < minAmountIn)) {
router = routerV1;
path = pulseXPath;
minAmountIn = v1AmountIn;
}
if (v2AmountIn != 0 && (minAmountIn == 0 || v2AmountIn < minAmountIn)) {
router = routerV2;
path = pulseXPath;
minAmountIn = v2AmountIn;
}
if (nineInchAmountIn != 0 && (minAmountIn == 0 || nineInchAmountIn < minAmountIn)) {
router = nineInchRouter;
path = nineInchPath;
minAmountIn = nineInchAmountIn;
}
}
function _updateUSDTAddress(address addr) internal {
usdtAddress = addr;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[47] private __gap;
}
Compiler Settings
{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":true},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"event","name":"EnteredRound","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":false},{"type":"uint256","name":"entryId","internalType":"uint256","indexed":false},{"type":"address","name":"player","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"expectation","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"FeeTaken","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":false},{"type":"uint256","name":"ufcAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"pspnAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint64","name":"version","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoundFinished","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":false},{"type":"uint8","name":"result","internalType":"uint8","indexed":false},{"type":"string","name":"winner","internalType":"string","indexed":false},{"type":"uint256","name":"totalAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"feeAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"pspnAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RoundStarted","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":false},{"type":"uint256","name":"closeAt","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_getAmountInWithoutException","inputs":[{"type":"address","name":"router","internalType":"contract IPulseXRouter02"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint256","name":"amountOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_getAmountOutWithoutException","inputs":[{"type":"address","name":"router","internalType":"contract IPulseXRouter02"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"router","internalType":"contract IPulseXRouter02"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint256","name":"minAmountIn","internalType":"uint256"}],"name":"_getOptimizedAmountIn","inputs":[{"type":"address","name":"tokenFrom","internalType":"address"},{"type":"address","name":"tokenTo","internalType":"address"},{"type":"uint256","name":"amountOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"router","internalType":"contract IPulseXRouter02"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint256","name":"maxAmountOut","internalType":"uint256"}],"name":"_getOptimizedAmountOut","inputs":[{"type":"address","name":"tokenFrom","internalType":"address"},{"type":"address","name":"tokenTo","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"pulseXPath","internalType":"address[]"},{"type":"address[]","name":"nineInchPath","internalType":"address[]"}],"name":"_getPossiblePaths","inputs":[{"type":"address","name":"tokenFrom","internalType":"address"},{"type":"address","name":"tokenTo","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"chunkSize","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createRound","inputs":[{"type":"string","name":"player1Name","internalType":"string"},{"type":"string","name":"player2Name","internalType":"string"},{"type":"uint256","name":"closeAt","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"enterRound","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"expectation","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"entryIds","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"finishRound","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256"},{"type":"uint8","name":"result","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct UFCFight.Round","components":[{"type":"uint256","name":"roundID","internalType":"uint256"},{"type":"string","name":"player1Name","internalType":"string"},{"type":"string","name":"player2Name","internalType":"string"},{"type":"uint256","name":"feeAmount","internalType":"uint256"},{"type":"uint256","name":"player1TotalAmount","internalType":"uint256"},{"type":"uint256","name":"player2TotalAmount","internalType":"uint256"},{"type":"tuple[]","name":"player1Bets","internalType":"struct UFCFight.Bet[]","components":[{"type":"address","name":"player","internalType":"address"},{"type":"uint256","name":"entryId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}]},{"type":"tuple[]","name":"player2Bets","internalType":"struct UFCFight.Bet[]","components":[{"type":"address","name":"player","internalType":"address"},{"type":"uint256","name":"entryId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}]},{"type":"uint48","name":"closeAt","internalType":"uint48"},{"type":"uint32","name":"player1LastIndex","internalType":"uint32"},{"type":"uint32","name":"player2LastIndex","internalType":"uint32"},{"type":"uint8","name":"result","internalType":"uint8"},{"type":"uint8","name":"status","internalType":"enum UFCFight.RoundStatus"}]}],"name":"getRound","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct UFCFight.Round[]","components":[{"type":"uint256","name":"roundID","internalType":"uint256"},{"type":"string","name":"player1Name","internalType":"string"},{"type":"string","name":"player2Name","internalType":"string"},{"type":"uint256","name":"feeAmount","internalType":"uint256"},{"type":"uint256","name":"player1TotalAmount","internalType":"uint256"},{"type":"uint256","name":"player2TotalAmount","internalType":"uint256"},{"type":"tuple[]","name":"player1Bets","internalType":"struct UFCFight.Bet[]","components":[{"type":"address","name":"player","internalType":"address"},{"type":"uint256","name":"entryId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}]},{"type":"tuple[]","name":"player2Bets","internalType":"struct UFCFight.Bet[]","components":[{"type":"address","name":"player","internalType":"address"},{"type":"uint256","name":"entryId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"}]},{"type":"uint48","name":"closeAt","internalType":"uint48"},{"type":"uint32","name":"player1LastIndex","internalType":"uint32"},{"type":"uint32","name":"player2LastIndex","internalType":"uint32"},{"type":"uint8","name":"result","internalType":"uint8"},{"type":"uint8","name":"status","internalType":"enum UFCFight.RoundStatus"}]}],"name":"getRounds","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTokenPrice","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"decimal","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"ufcAddress","internalType":"address"},{"type":"address","name":"pspnAddress","internalType":"address"},{"type":"address","name":"_routerAddress","internalType":"address"},{"type":"address","name":"_usdtAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isAdmin","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isTokenStable","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"pspn","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"roundIds","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"roundID","internalType":"uint256"},{"type":"string","name":"player1Name","internalType":"string"},{"type":"string","name":"player2Name","internalType":"string"},{"type":"uint256","name":"feeAmount","internalType":"uint256"},{"type":"uint256","name":"player1TotalAmount","internalType":"uint256"},{"type":"uint256","name":"player2TotalAmount","internalType":"uint256"},{"type":"uint48","name":"closeAt","internalType":"uint48"},{"type":"uint32","name":"player1LastIndex","internalType":"uint32"},{"type":"uint32","name":"player2LastIndex","internalType":"uint32"},{"type":"uint8","name":"result","internalType":"uint8"},{"type":"uint8","name":"status","internalType":"enum UFCFight.RoundStatus"}],"name":"rounds","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IPulseXRouter02"}],"name":"router","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAdmin","inputs":[{"type":"address","name":"addr","internalType":"address"},{"type":"bool","name":"value","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUFC"}],"name":"ufc","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"usdtAddress","inputs":[]}]
Contract Creation Code
0x60808060405234610016576130f1908161001c8239f35b600080fdfe6040608081526004908136101561001557600080fd5b600091823560e01c9081630e22e93f14610f6857816324d7806c14610f2a578163250fa2bc14610eec5781632e0b2d9914610c205781634b0bddd214610bca5781634fd3ba6f14610ab65781635c62e4b1146108475781635eef64ad146108285781636984d07014610745578163715018a6146106db57816378b43628146106b25781638c65c81f146105b35781638da5cb5b1461057d5781638f1327c0146104e45781639ab4a445146104bb578163ac593ed114610492578163c4a942cb14610473578163c9f7153c1461044a578163d462fcaa1461041f578163d7f942a314610403578163eb2715f9146103ac578163ebd8d2c71461038d578163f2fde38b1461035d578163f887ea4014610335578163f8c8765e14610166575063fe29d1db1461014157600080fd5b346101625760209061015b61015536611782565b91612f64565b9051908152f35b5080fd5b905034610331576080366003190112610331576101816113f0565b9061018a611406565b916001600160a01b03906044358281169081900361032d5760643592808416809403610329577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0095865460ff818a1c1615966001600160401b03821680159081610321575b6001149081610317575b15908161030e575b50610300575067ffffffffffffffff1981166001178855866102e1575b50816bffffffffffffffffffffffff60a01b9416846032541617603255168260335416176033553387526038602052858720600160ff1982541617905560646037556102686118d4565b6102706118d4565b61027933611860565b6102816118d4565b6102896118d4565b8187541617865560025416176002556102a0578280f35b805468ff00000000000000001916905551600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a138808280f35b68ffffffffffffffffff1916680100000000000000011787553861021e565b895163f92ee8a960e01b8152fd5b90501538610201565b303b1591506101f9565b8991506101ef565b8780fd5b8680fd5b8280fd5b505034610162578160031936011261016257905490516001600160a01b039091168152602090f35b833461038a57602036600319011261038a5761038761037a6113f0565b610382611827565b611860565b80f35b80fd5b5050346101625781600319360112610162576020906036549051908152f35b5050346101625780600319360112610162576103ff906103db6103cd6113f0565b6103d5611406565b906128ff565b6103f18394929451948486958652850190611451565b908382036020850152611451565b0390f35b5050346101625760209061015b61041936611782565b91612da4565b505034610162576103ff9061043c6104363661141c565b91612fb8565b90939192519384938461148e565b50503461016257806003193601126101625760209061015b61046a6113f0565b60243590612111565b5050346101625781600319360112610162576020906037549051908152f35b50503461016257816003193601126101625760335490516001600160a01b039091168152602090f35b50503461016257816003193601126101625760025490516001600160a01b039091168152602090f35b9050346103315760203660031901126103315761056461056a916103ff946101808551610510816112ed565b828152606060208201526060878201528260608201528260808201528260a0820152606060c0820152606060e08201528261010082015282610120820152826101408201528261016082015201523561164a565b50612033565b9051918291602083526020830190611578565b50503461016257816003193601126101625760008051602061309c8339815191525490516001600160a01b039091168152602090f35b82843461038a57602036600319011261038a5782359060345482101561038a57506105dd9061164a565b50916103ff835492805194610600866105f981600185016116d5565b0387611368565b81519161061b8361061481600286016116d5565b0384611368565b61065b60038301549583015491600860058501549401549461064e82519a8b9a8b526101608060208d01528b01906114b8565b91898303908a01526114b8565b946060870152608086015260a085015265ffffffffffff811660c085015263ffffffff808260301c1660e08601528160501c1661010085015260ff8160701c1661012085015260ff61014085019160781c16611555565b50503461016257816003193601126101625760325490516001600160a01b039091168152602090f35b833461038a578060031936011261038a576106f4611827565b60008051602061309c83398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b82843461038a578060031936011261038a576034546107638161176b565b9161077084519384611368565b8183526034815260209283810192827f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1855b83831061080357505050508451938085019181865251809252858501958260051b8601019392955b8287106107d75785850386f35b9091929382806107f3600193603f198a82030186528851611578565b96019201960195929190926107ca565b600988600192610816859b98999b612033565b815201920192019190969493966107a2565b5050346101625781600319360112610162576020906035549051908152f35b91905034610331578060031936011261033157813590602480359060ff82169182810361032d57338752603860205261088a600160ff868a205416151514611915565b610895323314611973565b61089e8561164a565b506008810196875460ff8160781c169060078210159081610aa457600183149081610a90575b508015610a84575b6108d96035548b106119b6565b818115610a62575b5015610a3057610a1e5760030361091e575b50505050505061090290611ab7565b61090a575080f35b805460ff60781b19166001607a1b17905580f35b610614919085610a125761093b600183015b8851948580926116d5565b6109488183015480611a32565b94600386029186830460031487151715610a015750506109dd889795936109029960037f6f41277d3793cb0a3aa5cfc141f5ba5c7b0ae8a4b4efa5d3dd8835933fbb477d9997958d60646109a0970496878095611f18565b9781548460781b9160ff60701b9060701b169061ffff60701b191617179055015560e087519788978b8952602089015287015260e08601906114b8565b926060850152608084015260a08301524260c08301520390a19038808080806108f3565b634e487b7160e01b8c52601190528afd5b61093b60028301610930565b634e487b7160e01b8a5260218252848afd5b875162461bcd60e51b8152602081850152600d818801526c0c6c2dcdcdee840ccd2dcd2e6d609b1b6044820152606490fd5b9050610a725760038214816108e1565b634e487b7160e01b8b5260218352858bfd5b505089600282146108cc565b905065ffffffffffff4291161115386108c4565b634e487b7160e01b8c5260218452868cfd5b50503461016257610ac63661141c565b6060949384939092610ad7916128ff565b9091610ae38184612dfa565b92610af8610af18383612ea8565b9284612f06565b9380151580610bc2575b610b9f575b5081151580610b8e575b610b6c575b505081151580610b5b575b610b37575b5050906103ff91519384938461148e565b945073eb45a3c4aedd0f47f345fb4c8a1802bb5740d725935091506103ff38610b26565b50831580610b215750838210610b21565b965073165c3410fc91ef562c50559f7d2289febed552d9955093503880610b16565b50851580610b115750858210610b11565b9097507398bf93ebf5c380c0e6ae8e192a7e2ae08edacc02965094508638610b07565b506001610b02565b505034610162578060031936011261016257610be46113f0565b9060243591821515809303610c1c57610bfb611827565b60018060a01b03168352603860205282209060ff8019835416911617905580f35b8380fd5b90506060366003190112610331578035906024803590604490813593610c47323314611973565b610c508661164a565b50610c5e60355488106119b6565b600881015460ff8160781c166007811015610eda57600103610eaa5765ffffffffffff4291161115610e7c576002861015610e45578415610e10576020929160649187158015610de8576006820190610cb8825492611a11565b5050838301610cc88a8254611a32565b90555b15610dd6576006610cdc92016119f5565b505b336bffffffffffffffffffffffff60a01b82541617815560365460018201558660028201556003429101558960018060a01b0360325416878b5197889687956323b872dd60e01b8752339087015230908601528401525af18015610dcc579260c092610d989695927f1da33b3de544dbd185334f3ed273885f3760b972a21d94ca736632fdd9d74fba95610d9e575b506036549580519384528660208501523390840152606083015260808201524260a0820152a161194e565b60365580f35b610dbe9060203d8111610dc5575b610db68183611368565b810190611a3f565b5038610d6d565b503d610dac565b85513d88823e3d90fd5b6007610de292016119f5565b50610cde565b6007820190610df8825492611a11565b505060058301610e098a8254611a32565b9055610ccb565b50701a5b9d985b1a59081d5cd9105b5bdd5b9d607a1b83601160649460208b519562461bcd60e51b8752860152840152820152fd5b507234b73b30b634b21032bc3832b1ba30ba34b7b760691b83601360649460208b519562461bcd60e51b8752860152840152820152fd5b506918995d0818db1bdcd95960b21b83600a60649460208b519562461bcd60e51b8752860152840152820152fd5b885162461bcd60e51b8152602081850152600c818601526b31b0b73737ba1032b73a32b960a11b81870152606490fd5b634e487b7160e01b8b5260218452848bfd5b5050346101625760203660031901126101625760209160ff9082906001600160a01b03610f176113f0565b1681526001855220541690519015158152f35b5050346101625760203660031901126101625760209160ff9082906001600160a01b03610f556113f0565b1681526038855220541690519015158152f35b905034610331576060366003190112610331576001600160401b0381358181116112e957610f9990369084016113a4565b916024358281116112e557610fb190369083016113a4565b9133865260209360388552600190610fd28260ff898b205416151514611915565b603454600160401b8110156112d2578083610ff0920160345561164a565b505060355494610fff8661164a565b5095865582860182518581116112bf578061101a835461169b565b94601f9586811161126e575b508a908d87841160011461120d5792611202575b5050600019600383901b1c191690851b1790555b600286019481519485116111ef5750611067855461169b565b8281116111ac575b50888792851160011461111d579380806008957fa359b664a68acd8839e42112eb50eff3408165e15074fde89ddb58a0db2e691d99956060999561110c9d9c9994611112575b50501b916000199060031b1c19161790555b019360443594600160781b65ffffffffffff87166fff000000000000000000ffffffffffff1983541617179055603554948151928684528301524290820152a161194e565b60355580f35b0151925038806110b5565b508489528689209293929190601f1984168a5b8181106111975750937fa359b664a68acd8839e42112eb50eff3408165e15074fde89ddb58a0db2e691d97936060979361110c9b9a9793836008981061117e575b505050811b0190556110c7565b015160001960f88460031b161c19169055388080611171565b82840151855593860193928901928901611130565b858a52878a208380870160051c8201928a88106111e6575b0160051c019084905b8281106111db57505061106f565b8b81550184906111cd565b925081926111c4565b634e487b7160e01b8a5260419052602489fd5b01519050388061103a565b8581528c8120899550929190601f198516908e5b828210611257575050841161123e575b505050811b01905561104e565b015160001960f88460031b161c19169055388080611231565b8385015186558b979095019493840193018e611221565b909150838d528a8d208680850160051c8201928d86106112b6575b859493910160051c9091019088908f5b8382106112a857505050611026565b81558594508991018f611299565b92508192611289565b634e487b7160e01b8b526041875260248bfd5b634e487b7160e01b895260418552602489fd5b8580fd5b8480fd5b6101a081019081106001600160401b0382111761130957604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161130957604052565b606081019081106001600160401b0382111761130957604052565b608081019081106001600160401b0382111761130957604052565b90601f801991011681019081106001600160401b0382111761130957604052565b6001600160401b03811161130957601f01601f191660200190565b81601f820112156113eb578035906113bb82611389565b926113c96040519485611368565b828452602083830101116113eb57816000926020809301838601378301015290565b600080fd5b600435906001600160a01b03821682036113eb57565b602435906001600160a01b03821682036113eb57565b60609060031901126113eb576001600160a01b039060043582811681036113eb579160243590811681036113eb579060443590565b90815180825260208080930193019160005b828110611471575050505090565b83516001600160a01b031685529381019392810192600101611463565b9392916114b39060409260018060a01b03168652606060208701526060860190611451565b930152565b919082519283825260005b8481106114e4575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016114c3565b90815180825260208080930193019160005b828110611518575050505090565b835180516001600160a01b03168652808301518684015260408082015190870152606090810151908601526080909401939281019260010161150a565b9060078210156115625752565b634e487b7160e01b600052602160045260246000fd5b9061164790825181526115f76115e56115b56115a360208701516101a08060208801528601906114b8565b604087015185820360408701526114b8565b606086015160608501526080860151608085015260a086015160a085015260c086015184820360c08601526114f8565b60e085015183820360e08501526114f8565b9261010065ffffffffffff81830151169083015263ffffffff610120818184015116908401526101409081830151169083015261016060ff81830151169083015261018080910151910190611555565b90565b603454811015611685576009906034600052027f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c10190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c921680156116cb575b60208310146116b557565b634e487b7160e01b600052602260045260246000fd5b91607f16916116aa565b90600092918054916116e68361169b565b9182825260019384811690816000146117485750600114611708575b50505050565b90919394506000526020928360002092846000945b838610611734575050505001019038808080611702565b80548587018301529401938590820161171d565b9294505050602093945060ff191683830152151560051b01019038808080611702565b6001600160401b0381116113095760051b60200190565b9060606003198301126113eb576001600160a01b0360043581811681036113eb5792602435906001600160401b0382116113eb57806023830112156113eb578160040135926117d08461176b565b936117de6040519586611368565b80855260209360248587019260051b8201019384116113eb57602401905b83821061180f5750505050509060443590565b813583811681036113eb5781529084019084016117fc565b60008051602061309c833981519152546001600160a01b0316330361184857565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b039081169081156118bb5760008051602061309c83398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561190357565b604051631afcd79f60e31b8152600490fd5b1561191c57565b60405162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b6044820152606490fd5b600019811461195d5760010190565b634e487b7160e01b600052601160045260246000fd5b1561197a57565b60405162461bcd60e51b815260206004820152601460248201527318dbdb9d1c9858dd081b9bdd08185b1b1bddd95960621b6044820152606490fd5b156119bd57565b60405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081c9bdd5b99081a5960821b6044820152606490fd5b80548210156116855760005260206000209060021b0190600090565b8054600160401b81101561130957611a2e916001820181556119f5565b9091565b9190820180921161195d57565b908160209103126113eb575180151581036113eb5790565b8181029291811591840414171561195d57565b8115611a74570490565b634e487b7160e01b600052601260045260246000fd5b63ffffffff80911690811461195d5760010190565b91909163ffffffff8080941691160191821161195d57565b611ac09061164a565b506008810180549160ff8360701c16600293848210600014611d13575015928315611d095760068201945b8415611cfe576004830154915b611b0d60049460058682015491015490611a32565b606181029080820460611490151715611ce95760649004918615611cd85763ffffffff865460301c16955b88549060005b63ffffffff8381611b4f8c85611a9f565b16109081611cc9575b5015611c36578860008c8a611bea611b8f8c611b8a8d8d611b82611b7c8b8d611a9f565b896119f5565b500154611a57565b611a6a565b92611bb060018060a01b0391611baa8360325416988a611a9f565b906119f5565b50541694604093845195868094819363a9059cbb60e01b835260209a8b98840160209093929193604081019460018060a01b031681520152565b03925af1908115611c2c575090611c09939291611c0e575b5050611a8a565b611b3e565b81611c2492903d10610dc557610db68183611368565b503880611c02565b513d6000823e3d90fd5b9450925096909750611c8a945063ffffffff959350600014611c9b57611c8590611c608484611a9f565b69ffffffff00000000000082549160301b169069ffffffff0000000000001916179055565b611a9f565b1614611c96575b600090565b600190565b611c8590611ca98484611a9f565b815463ffffffff60501b191660509190911b63ffffffff60501b16179055565b90506037549082161038611b58565b63ffffffff865460501c1695611b38565b601185634e487b7160e01b6000525260246000fd5b600583015491611af8565b6007820194611aeb565b939192949050600683019283549463ffffffff95868260301c1610600014611e3857505083855460301c169483549460005b8682611d518a84611a9f565b161080611e2b575b15611e155784611d72611d6c8a84611a9f565b886119f5565b50015460619081810291818304149015171561195d57600089606492611df260018060a01b03611db0611daa82603254169589611a9f565b8d6119f5565b50546040805163a9059cbb60e01b8152929091166001600160a01b03166004830152959092046024830152602094919391928592859283919082906044820190565b03925af1908115611c2c575090611e10939291611c0e575050611a8a565b611d45565b91945050611c919450611c609250949094611a9f565b5060375482821610611d59565b85945094600791969560501c16950192835490818710600014611f0c5760005b8282611e648a84611a9f565b161080611eff575b15611eda5784611e7f611d6c8a84611a9f565b50015460619081810291818304149015171561195d57600089606492611eb760018060a01b03611db0611daa82603254169589611a9f565b03925af1908115611c2c575090611ed5939291611c0e575050611a8a565b611e58565b9195611c85919550611ef49450969296611ca98484611a9f565b1603611c9157600190565b5060375482821610611e6c565b50509350505050600190565b9190918215611f7b5760807f9c2d2363c6a2345ff8422066fb7d146f757ed4e7d5d59006ea8db04128d35da691611f6060018060a01b03868160325416916033541682612254565b946040519182526020820152846040820152426060820152a1565b5060009150565b90815491611f8f8361176b565b92604093611f9f85519182611368565b818152809460208092019360009081528281209181955b858710611fc65750505050505050565b8151608081018181106001600160401b0382111761201f57835284546001600160a01b03168152600180860154878301526002860154828501526003860154606083015290825296909601956004909301928401611fb6565b634e487b7160e01b85526041600452602485fd5b90604051612040816112ed565b60ff60088294805484526040516120658161205e81600186016116d5565b0382611368565b602085015260405161207e8161205e81600286016116d5565b60408501526003810154606085015260048101546080850152600581015460a08501526120ad60068201611f82565b60c08501526120be60078201611f82565b60e0850152015465ffffffffffff811661010084015263ffffffff808260301c166101208501528160501c16610140840152818160701c1661016084015260781c16906007821015611562576101800152565b60025460405163313ce56760e01b8152926001600160a01b0391821691602085600481865afa94851561224857600095612209575b5083169283600052600160205260ff604060002054166121f857600193738d36123903f504eb81eeb832727af517c0db26bd81149081156121da575b506121cf575b604d821161195d5760ff926104366121a393600a0a86611a57565b949150501660120360ff811161195d5760ff16604d811161195d5761164792611b8a91600a0a90611a57565b620186a09350612188565b73a27ade5806ded801b93499c6fa23cc8dc9ac55ea91501438612182565b5050505050670de0b6b3a764000090565b6020959195813d8211612240575b8161222460209383611368565b8101031261016257519060ff8216820361038a57509338612146565b3d9150612217565b6040513d6000823e3d90fd5b919091600082156127d7576001600160a01b0394848616948387169384871461272957612282918691612fb8565b509095909490801561264d576040958651976370a0823160e01b93848a528a86169a6004968c888d01526020998a8d6024818a5afa9c8d1561264357908e92918b9e61260a575b50918c8b969492848c999795156000146123c057505051637ff36ab560e01b815296870186905260806024880152869485939291849161230d906084840190611451565b9060448301524260648301520393165af180156123b6579186949391602493612394575b505b8751998a94859384528301525afa92831561238a57509161235a575b506116479250612819565b905082813d8311612383575b6123708183611368565b810103126113eb5761164791513861234f565b503d612366565b51903d90823e3d90fd5b6123af903d8089833e6123a78183611368565b810190612845565b5038612331565b87513d87823e3d90fd5b9496978e92919993508490541690519283809263ef8ef56f60e01b82525afa90811561260057928d8c848f95899897958f9b9a9684916125d3575b501684036124cc57915163095ea7b360e01b81526001600160a01b039290961691821698860198895260208901939093529684928391829060400103925af180156124c2578994928996949286926124a5575b5061246e8d51978896879586946338ed173960e01b8652429386016127df565b03925af180156123b657918694939160249361248b575b50612333565b61249e903d8089833e6123a78183611368565b5038612485565b6124bb908d803d10610dc557610db68183611368565b503861244e565b8b513d8b823e3d90fd5b915163095ea7b360e01b81526001600160a01b039290961691821698860198895260208901939093529684928391829060400103925af180156124c2576125b6575b50868873eb45a3c4aedd0f47f345fb4c8a1802bb5740d7258514612590575050823b15610329579186939188809461255b8d5197889687958694635c11d79560e01b8652429386016127df565b03925af180156123b65790869493929161257a575b5090602491612333565b94612588602493929661131f565b949091612570565b8b516338ed173960e01b81529590948694909385938793859361246e93429386016127df565b6125cc908a3d8c11610dc557610db68183611368565b503861250e565b6125f39150883d8a116125f9575b6125eb8183611368565b810190612826565b386123fb565b503d6125e1565b8d513d8d823e3d90fd5b8c80929f50819394503d831161263c575b6126258183611368565b8101031261263857519b8d91908c6122c9565b8980fd5b503d61261b565b8c513d8c823e3d90fd5b5060405163095ea7b360e01b8152959096166001600160a01b0381166004870152602486018790529196959194909392879291906020908290604490829087905af1801561271e57612700575b50833194803b156103315784836126ca956040519687958694859363791ac94760e01b85524292600486016127df565b03925af180156126f5576116479495506126e6575b5031612819565b6126ef9061131f565b386126df565b6040513d87823e3d90fd5b6127179060203d8111610dc557610db68183611368565b503861269a565b6040513d85823e3d90fd5b505091909294859450821691823003612745575b505050505090565b8161277157505081808094819382f11561276557505b803880808061273d565b604051903d90823e3d90fd5b60405163a9059cbb60e01b81526001600160a01b039190911660048201526024810194909452602091508390604490829085905af190811561276557506127b9575b5061275b565b6127d09060203d8111610dc557610db68183611368565b50386127b3565b935050505090565b90608092612805919695949683526000602084015260a0604084015260a0830190611451565b6001600160a01b0390951660608201520152565b9190820391821161195d57565b908160209103126113eb57516001600160a01b03811681036113eb5790565b60209081818403126113eb578051906001600160401b0382116113eb57019180601f840112156113eb57825161287a8161176b565b936128886040519586611368565b818552838086019260051b8201019283116113eb578301905b8282106128af575050505090565b815181529083019083016128a1565b8051156116855760200190565b8051600110156116855760400190565b8051600210156116855760600190565b80518210156116855760209160051b010190565b6000546040805163ef8ef56f60e01b8152909492916020916001600160a01b039183908290600490829086165afa908115612b475782918291600091612b2a575b50169516928584141580612b21575b15612aa9571680158015612aa0575b156129dd57506129da90606086519661297688611332565b600288528036848a013784612995898961298f826128be565b526128cb565b5251916129a18361134d565b60038352369083013780946129b5826128be565b52733ca80d83277e721171284667829c686527b8b3c56129d4826128cb565b526128db565b52565b94733ca80d83277e721171284667829c686527b8b3c594858703612a52579083612a316129da9493835190612a118261134d565b6003825260603687840137819a612a27836128be565b526129d4826128cb565b52805191612a3e83611332565b600283523690830137809461298f826128be565b959460608285612a806129da969551612a6a8161134d565b60038152843688830137809b8b612a27836128be565b525192612a8c8461134d565b6003845236908401378195612a27836128be565b5084811461295e565b1694733ca80d83277e721171284667829c686527b8b3c59492858703612af35750908183612a316129da9451612ade81611332565b60028152833686830137809961298f826128be565b9295946060826129da94935198612b098a611332565b60028a528136868c0137612a808a8a61298f826128be565b5083151561294f565b612b419150853d87116125f9576125eb8183611368565b38612940565b87513d6000823e3d90fd5b60009060033d11612b5f57565b905060046000803e60005160e01c90565b600060443d1061164757604051600319913d83016004833e81516001600160401b03918282113d602484011117612bcd57818401948551938411612bd5573d85010160208487010111612bcd575061164792910160200190611368565b949350505050565b50949350505050565b3d15612c09573d90612bef82611389565b91612bfd6040519384611368565b82523d6000602084013e565b606090565b90612c3f92916040519163d06ca61f60e01b8352600483015260406024830152818060009586936044830190611451565b03817398bf93ebf5c380c0e6ae8e192a7e2ae08edacc025afa839181612cc8575b50612c96575090612c6f612b52565b6308c379a014612c86575b612c82612bde565b5090565b612c8e612b70565b15612c7a5790565b8051600019810191908211612cb457612cb09293506128eb565b5190565b634e487b7160e01b84526011600452602484fd5b612cdd9192503d8086833e6123a78183611368565b9038612c60565b90612d1592916040519163d06ca61f60e01b8352600483015260406024830152818060009586936044830190611451565b038173165c3410fc91ef562c50559f7d2289febed552d95afa839181612cc85750612c96575090612c6f612b52565b90612d7592916040519163d06ca61f60e01b8352600483015260406024830152818060009586936044830190611451565b038173eb45a3c4aedd0f47f345fb4c8a1802bb5740d7255afa839181612cc85750612c96575090612c6f612b52565b90612dd7939260405192839163d06ca61f60e01b8352600483015260406024830152818060009788956044830190611451565b03916001600160a01b03165afa839181612cc85750612c96575090612c6f612b52565b600090612e299260405193849283926307c0329d60e21b84526004840152604060248401526044830190611451565b03817398bf93ebf5c380c0e6ae8e192a7e2ae08edacc025afa60009181612e8d575b50612e845750612e59612b52565b6308c379a014612e72575b612e6c612bde565b50600090565b612e7a612b70565b15612e6457600090565b612cb0906128be565b612ea191923d8091833e6123a78183611368565b9038612e4b565b600090612ed79260405193849283926307c0329d60e21b84526004840152604060248401526044830190611451565b038173165c3410fc91ef562c50559f7d2289febed552d95afa60009181612e8d5750612e845750612e59612b52565b600090612f359260405193849283926307c0329d60e21b84526004840152604060248401526044830190611451565b038173eb45a3c4aedd0f47f345fb4c8a1802bb5740d7255afa60009181612e8d5750612e845750612e59612b52565b90600091612f95936040518095819482936307c0329d60e21b84526004840152604060248401526044830190611451565b03916001600160a01b03165afa60009181612e8d5750612e845750612e59612b52565b909192600093612fcc6060946000946128ff565b9190612fd88282612c0e565b91612fed612fe68284612ce4565b9185612d44565b9280151580613096575b613071575b5080151580613068575b613045575b50508015158061303c575b61301e575050565b73eb45a3c4aedd0f47f345fb4c8a1802bb5740d72595509093509150565b50838111613016565b73165c3410fc91ef562c50559f7d2289febed552d997509095509350388061300b565b50858111613006565b9650945095507398bf93ebf5c380c0e6ae8e192a7e2ae08edacc029580959438612ffc565b612ff756fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300a26469706673582212208658ee893e0e7f4f0d1c7c5ba12508a7cd40b2103a55e15ef7e0b13338729fb464736f6c63430008140033
Deployed ByteCode
0x6040608081526004908136101561001557600080fd5b600091823560e01c9081630e22e93f14610f6857816324d7806c14610f2a578163250fa2bc14610eec5781632e0b2d9914610c205781634b0bddd214610bca5781634fd3ba6f14610ab65781635c62e4b1146108475781635eef64ad146108285781636984d07014610745578163715018a6146106db57816378b43628146106b25781638c65c81f146105b35781638da5cb5b1461057d5781638f1327c0146104e45781639ab4a445146104bb578163ac593ed114610492578163c4a942cb14610473578163c9f7153c1461044a578163d462fcaa1461041f578163d7f942a314610403578163eb2715f9146103ac578163ebd8d2c71461038d578163f2fde38b1461035d578163f887ea4014610335578163f8c8765e14610166575063fe29d1db1461014157600080fd5b346101625760209061015b61015536611782565b91612f64565b9051908152f35b5080fd5b905034610331576080366003190112610331576101816113f0565b9061018a611406565b916001600160a01b03906044358281169081900361032d5760643592808416809403610329577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0095865460ff818a1c1615966001600160401b03821680159081610321575b6001149081610317575b15908161030e575b50610300575067ffffffffffffffff1981166001178855866102e1575b50816bffffffffffffffffffffffff60a01b9416846032541617603255168260335416176033553387526038602052858720600160ff1982541617905560646037556102686118d4565b6102706118d4565b61027933611860565b6102816118d4565b6102896118d4565b8187541617865560025416176002556102a0578280f35b805468ff00000000000000001916905551600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a138808280f35b68ffffffffffffffffff1916680100000000000000011787553861021e565b895163f92ee8a960e01b8152fd5b90501538610201565b303b1591506101f9565b8991506101ef565b8780fd5b8680fd5b8280fd5b505034610162578160031936011261016257905490516001600160a01b039091168152602090f35b833461038a57602036600319011261038a5761038761037a6113f0565b610382611827565b611860565b80f35b80fd5b5050346101625781600319360112610162576020906036549051908152f35b5050346101625780600319360112610162576103ff906103db6103cd6113f0565b6103d5611406565b906128ff565b6103f18394929451948486958652850190611451565b908382036020850152611451565b0390f35b5050346101625760209061015b61041936611782565b91612da4565b505034610162576103ff9061043c6104363661141c565b91612fb8565b90939192519384938461148e565b50503461016257806003193601126101625760209061015b61046a6113f0565b60243590612111565b5050346101625781600319360112610162576020906037549051908152f35b50503461016257816003193601126101625760335490516001600160a01b039091168152602090f35b50503461016257816003193601126101625760025490516001600160a01b039091168152602090f35b9050346103315760203660031901126103315761056461056a916103ff946101808551610510816112ed565b828152606060208201526060878201528260608201528260808201528260a0820152606060c0820152606060e08201528261010082015282610120820152826101408201528261016082015201523561164a565b50612033565b9051918291602083526020830190611578565b50503461016257816003193601126101625760008051602061309c8339815191525490516001600160a01b039091168152602090f35b82843461038a57602036600319011261038a5782359060345482101561038a57506105dd9061164a565b50916103ff835492805194610600866105f981600185016116d5565b0387611368565b81519161061b8361061481600286016116d5565b0384611368565b61065b60038301549583015491600860058501549401549461064e82519a8b9a8b526101608060208d01528b01906114b8565b91898303908a01526114b8565b946060870152608086015260a085015265ffffffffffff811660c085015263ffffffff808260301c1660e08601528160501c1661010085015260ff8160701c1661012085015260ff61014085019160781c16611555565b50503461016257816003193601126101625760325490516001600160a01b039091168152602090f35b833461038a578060031936011261038a576106f4611827565b60008051602061309c83398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b82843461038a578060031936011261038a576034546107638161176b565b9161077084519384611368565b8183526034815260209283810192827f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1855b83831061080357505050508451938085019181865251809252858501958260051b8601019392955b8287106107d75785850386f35b9091929382806107f3600193603f198a82030186528851611578565b96019201960195929190926107ca565b600988600192610816859b98999b612033565b815201920192019190969493966107a2565b5050346101625781600319360112610162576020906035549051908152f35b91905034610331578060031936011261033157813590602480359060ff82169182810361032d57338752603860205261088a600160ff868a205416151514611915565b610895323314611973565b61089e8561164a565b506008810196875460ff8160781c169060078210159081610aa457600183149081610a90575b508015610a84575b6108d96035548b106119b6565b818115610a62575b5015610a3057610a1e5760030361091e575b50505050505061090290611ab7565b61090a575080f35b805460ff60781b19166001607a1b17905580f35b610614919085610a125761093b600183015b8851948580926116d5565b6109488183015480611a32565b94600386029186830460031487151715610a015750506109dd889795936109029960037f6f41277d3793cb0a3aa5cfc141f5ba5c7b0ae8a4b4efa5d3dd8835933fbb477d9997958d60646109a0970496878095611f18565b9781548460781b9160ff60701b9060701b169061ffff60701b191617179055015560e087519788978b8952602089015287015260e08601906114b8565b926060850152608084015260a08301524260c08301520390a19038808080806108f3565b634e487b7160e01b8c52601190528afd5b61093b60028301610930565b634e487b7160e01b8a5260218252848afd5b875162461bcd60e51b8152602081850152600d818801526c0c6c2dcdcdee840ccd2dcd2e6d609b1b6044820152606490fd5b9050610a725760038214816108e1565b634e487b7160e01b8b5260218352858bfd5b505089600282146108cc565b905065ffffffffffff4291161115386108c4565b634e487b7160e01b8c5260218452868cfd5b50503461016257610ac63661141c565b6060949384939092610ad7916128ff565b9091610ae38184612dfa565b92610af8610af18383612ea8565b9284612f06565b9380151580610bc2575b610b9f575b5081151580610b8e575b610b6c575b505081151580610b5b575b610b37575b5050906103ff91519384938461148e565b945073eb45a3c4aedd0f47f345fb4c8a1802bb5740d725935091506103ff38610b26565b50831580610b215750838210610b21565b965073165c3410fc91ef562c50559f7d2289febed552d9955093503880610b16565b50851580610b115750858210610b11565b9097507398bf93ebf5c380c0e6ae8e192a7e2ae08edacc02965094508638610b07565b506001610b02565b505034610162578060031936011261016257610be46113f0565b9060243591821515809303610c1c57610bfb611827565b60018060a01b03168352603860205282209060ff8019835416911617905580f35b8380fd5b90506060366003190112610331578035906024803590604490813593610c47323314611973565b610c508661164a565b50610c5e60355488106119b6565b600881015460ff8160781c166007811015610eda57600103610eaa5765ffffffffffff4291161115610e7c576002861015610e45578415610e10576020929160649187158015610de8576006820190610cb8825492611a11565b5050838301610cc88a8254611a32565b90555b15610dd6576006610cdc92016119f5565b505b336bffffffffffffffffffffffff60a01b82541617815560365460018201558660028201556003429101558960018060a01b0360325416878b5197889687956323b872dd60e01b8752339087015230908601528401525af18015610dcc579260c092610d989695927f1da33b3de544dbd185334f3ed273885f3760b972a21d94ca736632fdd9d74fba95610d9e575b506036549580519384528660208501523390840152606083015260808201524260a0820152a161194e565b60365580f35b610dbe9060203d8111610dc5575b610db68183611368565b810190611a3f565b5038610d6d565b503d610dac565b85513d88823e3d90fd5b6007610de292016119f5565b50610cde565b6007820190610df8825492611a11565b505060058301610e098a8254611a32565b9055610ccb565b50701a5b9d985b1a59081d5cd9105b5bdd5b9d607a1b83601160649460208b519562461bcd60e51b8752860152840152820152fd5b507234b73b30b634b21032bc3832b1ba30ba34b7b760691b83601360649460208b519562461bcd60e51b8752860152840152820152fd5b506918995d0818db1bdcd95960b21b83600a60649460208b519562461bcd60e51b8752860152840152820152fd5b885162461bcd60e51b8152602081850152600c818601526b31b0b73737ba1032b73a32b960a11b81870152606490fd5b634e487b7160e01b8b5260218452848bfd5b5050346101625760203660031901126101625760209160ff9082906001600160a01b03610f176113f0565b1681526001855220541690519015158152f35b5050346101625760203660031901126101625760209160ff9082906001600160a01b03610f556113f0565b1681526038855220541690519015158152f35b905034610331576060366003190112610331576001600160401b0381358181116112e957610f9990369084016113a4565b916024358281116112e557610fb190369083016113a4565b9133865260209360388552600190610fd28260ff898b205416151514611915565b603454600160401b8110156112d2578083610ff0920160345561164a565b505060355494610fff8661164a565b5095865582860182518581116112bf578061101a835461169b565b94601f9586811161126e575b508a908d87841160011461120d5792611202575b5050600019600383901b1c191690851b1790555b600286019481519485116111ef5750611067855461169b565b8281116111ac575b50888792851160011461111d579380806008957fa359b664a68acd8839e42112eb50eff3408165e15074fde89ddb58a0db2e691d99956060999561110c9d9c9994611112575b50501b916000199060031b1c19161790555b019360443594600160781b65ffffffffffff87166fff000000000000000000ffffffffffff1983541617179055603554948151928684528301524290820152a161194e565b60355580f35b0151925038806110b5565b508489528689209293929190601f1984168a5b8181106111975750937fa359b664a68acd8839e42112eb50eff3408165e15074fde89ddb58a0db2e691d97936060979361110c9b9a9793836008981061117e575b505050811b0190556110c7565b015160001960f88460031b161c19169055388080611171565b82840151855593860193928901928901611130565b858a52878a208380870160051c8201928a88106111e6575b0160051c019084905b8281106111db57505061106f565b8b81550184906111cd565b925081926111c4565b634e487b7160e01b8a5260419052602489fd5b01519050388061103a565b8581528c8120899550929190601f198516908e5b828210611257575050841161123e575b505050811b01905561104e565b015160001960f88460031b161c19169055388080611231565b8385015186558b979095019493840193018e611221565b909150838d528a8d208680850160051c8201928d86106112b6575b859493910160051c9091019088908f5b8382106112a857505050611026565b81558594508991018f611299565b92508192611289565b634e487b7160e01b8b526041875260248bfd5b634e487b7160e01b895260418552602489fd5b8580fd5b8480fd5b6101a081019081106001600160401b0382111761130957604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161130957604052565b606081019081106001600160401b0382111761130957604052565b608081019081106001600160401b0382111761130957604052565b90601f801991011681019081106001600160401b0382111761130957604052565b6001600160401b03811161130957601f01601f191660200190565b81601f820112156113eb578035906113bb82611389565b926113c96040519485611368565b828452602083830101116113eb57816000926020809301838601378301015290565b600080fd5b600435906001600160a01b03821682036113eb57565b602435906001600160a01b03821682036113eb57565b60609060031901126113eb576001600160a01b039060043582811681036113eb579160243590811681036113eb579060443590565b90815180825260208080930193019160005b828110611471575050505090565b83516001600160a01b031685529381019392810192600101611463565b9392916114b39060409260018060a01b03168652606060208701526060860190611451565b930152565b919082519283825260005b8481106114e4575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016114c3565b90815180825260208080930193019160005b828110611518575050505090565b835180516001600160a01b03168652808301518684015260408082015190870152606090810151908601526080909401939281019260010161150a565b9060078210156115625752565b634e487b7160e01b600052602160045260246000fd5b9061164790825181526115f76115e56115b56115a360208701516101a08060208801528601906114b8565b604087015185820360408701526114b8565b606086015160608501526080860151608085015260a086015160a085015260c086015184820360c08601526114f8565b60e085015183820360e08501526114f8565b9261010065ffffffffffff81830151169083015263ffffffff610120818184015116908401526101409081830151169083015261016060ff81830151169083015261018080910151910190611555565b90565b603454811015611685576009906034600052027f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c10190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c921680156116cb575b60208310146116b557565b634e487b7160e01b600052602260045260246000fd5b91607f16916116aa565b90600092918054916116e68361169b565b9182825260019384811690816000146117485750600114611708575b50505050565b90919394506000526020928360002092846000945b838610611734575050505001019038808080611702565b80548587018301529401938590820161171d565b9294505050602093945060ff191683830152151560051b01019038808080611702565b6001600160401b0381116113095760051b60200190565b9060606003198301126113eb576001600160a01b0360043581811681036113eb5792602435906001600160401b0382116113eb57806023830112156113eb578160040135926117d08461176b565b936117de6040519586611368565b80855260209360248587019260051b8201019384116113eb57602401905b83821061180f5750505050509060443590565b813583811681036113eb5781529084019084016117fc565b60008051602061309c833981519152546001600160a01b0316330361184857565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b039081169081156118bb5760008051602061309c83398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561190357565b604051631afcd79f60e31b8152600490fd5b1561191c57565b60405162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b6044820152606490fd5b600019811461195d5760010190565b634e487b7160e01b600052601160045260246000fd5b1561197a57565b60405162461bcd60e51b815260206004820152601460248201527318dbdb9d1c9858dd081b9bdd08185b1b1bddd95960621b6044820152606490fd5b156119bd57565b60405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081c9bdd5b99081a5960821b6044820152606490fd5b80548210156116855760005260206000209060021b0190600090565b8054600160401b81101561130957611a2e916001820181556119f5565b9091565b9190820180921161195d57565b908160209103126113eb575180151581036113eb5790565b8181029291811591840414171561195d57565b8115611a74570490565b634e487b7160e01b600052601260045260246000fd5b63ffffffff80911690811461195d5760010190565b91909163ffffffff8080941691160191821161195d57565b611ac09061164a565b506008810180549160ff8360701c16600293848210600014611d13575015928315611d095760068201945b8415611cfe576004830154915b611b0d60049460058682015491015490611a32565b606181029080820460611490151715611ce95760649004918615611cd85763ffffffff865460301c16955b88549060005b63ffffffff8381611b4f8c85611a9f565b16109081611cc9575b5015611c36578860008c8a611bea611b8f8c611b8a8d8d611b82611b7c8b8d611a9f565b896119f5565b500154611a57565b611a6a565b92611bb060018060a01b0391611baa8360325416988a611a9f565b906119f5565b50541694604093845195868094819363a9059cbb60e01b835260209a8b98840160209093929193604081019460018060a01b031681520152565b03925af1908115611c2c575090611c09939291611c0e575b5050611a8a565b611b3e565b81611c2492903d10610dc557610db68183611368565b503880611c02565b513d6000823e3d90fd5b9450925096909750611c8a945063ffffffff959350600014611c9b57611c8590611c608484611a9f565b69ffffffff00000000000082549160301b169069ffffffff0000000000001916179055565b611a9f565b1614611c96575b600090565b600190565b611c8590611ca98484611a9f565b815463ffffffff60501b191660509190911b63ffffffff60501b16179055565b90506037549082161038611b58565b63ffffffff865460501c1695611b38565b601185634e487b7160e01b6000525260246000fd5b600583015491611af8565b6007820194611aeb565b939192949050600683019283549463ffffffff95868260301c1610600014611e3857505083855460301c169483549460005b8682611d518a84611a9f565b161080611e2b575b15611e155784611d72611d6c8a84611a9f565b886119f5565b50015460619081810291818304149015171561195d57600089606492611df260018060a01b03611db0611daa82603254169589611a9f565b8d6119f5565b50546040805163a9059cbb60e01b8152929091166001600160a01b03166004830152959092046024830152602094919391928592859283919082906044820190565b03925af1908115611c2c575090611e10939291611c0e575050611a8a565b611d45565b91945050611c919450611c609250949094611a9f565b5060375482821610611d59565b85945094600791969560501c16950192835490818710600014611f0c5760005b8282611e648a84611a9f565b161080611eff575b15611eda5784611e7f611d6c8a84611a9f565b50015460619081810291818304149015171561195d57600089606492611eb760018060a01b03611db0611daa82603254169589611a9f565b03925af1908115611c2c575090611ed5939291611c0e575050611a8a565b611e58565b9195611c85919550611ef49450969296611ca98484611a9f565b1603611c9157600190565b5060375482821610611e6c565b50509350505050600190565b9190918215611f7b5760807f9c2d2363c6a2345ff8422066fb7d146f757ed4e7d5d59006ea8db04128d35da691611f6060018060a01b03868160325416916033541682612254565b946040519182526020820152846040820152426060820152a1565b5060009150565b90815491611f8f8361176b565b92604093611f9f85519182611368565b818152809460208092019360009081528281209181955b858710611fc65750505050505050565b8151608081018181106001600160401b0382111761201f57835284546001600160a01b03168152600180860154878301526002860154828501526003860154606083015290825296909601956004909301928401611fb6565b634e487b7160e01b85526041600452602485fd5b90604051612040816112ed565b60ff60088294805484526040516120658161205e81600186016116d5565b0382611368565b602085015260405161207e8161205e81600286016116d5565b60408501526003810154606085015260048101546080850152600581015460a08501526120ad60068201611f82565b60c08501526120be60078201611f82565b60e0850152015465ffffffffffff811661010084015263ffffffff808260301c166101208501528160501c16610140840152818160701c1661016084015260781c16906007821015611562576101800152565b60025460405163313ce56760e01b8152926001600160a01b0391821691602085600481865afa94851561224857600095612209575b5083169283600052600160205260ff604060002054166121f857600193738d36123903f504eb81eeb832727af517c0db26bd81149081156121da575b506121cf575b604d821161195d5760ff926104366121a393600a0a86611a57565b949150501660120360ff811161195d5760ff16604d811161195d5761164792611b8a91600a0a90611a57565b620186a09350612188565b73a27ade5806ded801b93499c6fa23cc8dc9ac55ea91501438612182565b5050505050670de0b6b3a764000090565b6020959195813d8211612240575b8161222460209383611368565b8101031261016257519060ff8216820361038a57509338612146565b3d9150612217565b6040513d6000823e3d90fd5b919091600082156127d7576001600160a01b0394848616948387169384871461272957612282918691612fb8565b509095909490801561264d576040958651976370a0823160e01b93848a528a86169a6004968c888d01526020998a8d6024818a5afa9c8d1561264357908e92918b9e61260a575b50918c8b969492848c999795156000146123c057505051637ff36ab560e01b815296870186905260806024880152869485939291849161230d906084840190611451565b9060448301524260648301520393165af180156123b6579186949391602493612394575b505b8751998a94859384528301525afa92831561238a57509161235a575b506116479250612819565b905082813d8311612383575b6123708183611368565b810103126113eb5761164791513861234f565b503d612366565b51903d90823e3d90fd5b6123af903d8089833e6123a78183611368565b810190612845565b5038612331565b87513d87823e3d90fd5b9496978e92919993508490541690519283809263ef8ef56f60e01b82525afa90811561260057928d8c848f95899897958f9b9a9684916125d3575b501684036124cc57915163095ea7b360e01b81526001600160a01b039290961691821698860198895260208901939093529684928391829060400103925af180156124c2578994928996949286926124a5575b5061246e8d51978896879586946338ed173960e01b8652429386016127df565b03925af180156123b657918694939160249361248b575b50612333565b61249e903d8089833e6123a78183611368565b5038612485565b6124bb908d803d10610dc557610db68183611368565b503861244e565b8b513d8b823e3d90fd5b915163095ea7b360e01b81526001600160a01b039290961691821698860198895260208901939093529684928391829060400103925af180156124c2576125b6575b50868873eb45a3c4aedd0f47f345fb4c8a1802bb5740d7258514612590575050823b15610329579186939188809461255b8d5197889687958694635c11d79560e01b8652429386016127df565b03925af180156123b65790869493929161257a575b5090602491612333565b94612588602493929661131f565b949091612570565b8b516338ed173960e01b81529590948694909385938793859361246e93429386016127df565b6125cc908a3d8c11610dc557610db68183611368565b503861250e565b6125f39150883d8a116125f9575b6125eb8183611368565b810190612826565b386123fb565b503d6125e1565b8d513d8d823e3d90fd5b8c80929f50819394503d831161263c575b6126258183611368565b8101031261263857519b8d91908c6122c9565b8980fd5b503d61261b565b8c513d8c823e3d90fd5b5060405163095ea7b360e01b8152959096166001600160a01b0381166004870152602486018790529196959194909392879291906020908290604490829087905af1801561271e57612700575b50833194803b156103315784836126ca956040519687958694859363791ac94760e01b85524292600486016127df565b03925af180156126f5576116479495506126e6575b5031612819565b6126ef9061131f565b386126df565b6040513d87823e3d90fd5b6127179060203d8111610dc557610db68183611368565b503861269a565b6040513d85823e3d90fd5b505091909294859450821691823003612745575b505050505090565b8161277157505081808094819382f11561276557505b803880808061273d565b604051903d90823e3d90fd5b60405163a9059cbb60e01b81526001600160a01b039190911660048201526024810194909452602091508390604490829085905af190811561276557506127b9575b5061275b565b6127d09060203d8111610dc557610db68183611368565b50386127b3565b935050505090565b90608092612805919695949683526000602084015260a0604084015260a0830190611451565b6001600160a01b0390951660608201520152565b9190820391821161195d57565b908160209103126113eb57516001600160a01b03811681036113eb5790565b60209081818403126113eb578051906001600160401b0382116113eb57019180601f840112156113eb57825161287a8161176b565b936128886040519586611368565b818552838086019260051b8201019283116113eb578301905b8282106128af575050505090565b815181529083019083016128a1565b8051156116855760200190565b8051600110156116855760400190565b8051600210156116855760600190565b80518210156116855760209160051b010190565b6000546040805163ef8ef56f60e01b8152909492916020916001600160a01b039183908290600490829086165afa908115612b475782918291600091612b2a575b50169516928584141580612b21575b15612aa9571680158015612aa0575b156129dd57506129da90606086519661297688611332565b600288528036848a013784612995898961298f826128be565b526128cb565b5251916129a18361134d565b60038352369083013780946129b5826128be565b52733ca80d83277e721171284667829c686527b8b3c56129d4826128cb565b526128db565b52565b94733ca80d83277e721171284667829c686527b8b3c594858703612a52579083612a316129da9493835190612a118261134d565b6003825260603687840137819a612a27836128be565b526129d4826128cb565b52805191612a3e83611332565b600283523690830137809461298f826128be565b959460608285612a806129da969551612a6a8161134d565b60038152843688830137809b8b612a27836128be565b525192612a8c8461134d565b6003845236908401378195612a27836128be565b5084811461295e565b1694733ca80d83277e721171284667829c686527b8b3c59492858703612af35750908183612a316129da9451612ade81611332565b60028152833686830137809961298f826128be565b9295946060826129da94935198612b098a611332565b60028a528136868c0137612a808a8a61298f826128be565b5083151561294f565b612b419150853d87116125f9576125eb8183611368565b38612940565b87513d6000823e3d90fd5b60009060033d11612b5f57565b905060046000803e60005160e01c90565b600060443d1061164757604051600319913d83016004833e81516001600160401b03918282113d602484011117612bcd57818401948551938411612bd5573d85010160208487010111612bcd575061164792910160200190611368565b949350505050565b50949350505050565b3d15612c09573d90612bef82611389565b91612bfd6040519384611368565b82523d6000602084013e565b606090565b90612c3f92916040519163d06ca61f60e01b8352600483015260406024830152818060009586936044830190611451565b03817398bf93ebf5c380c0e6ae8e192a7e2ae08edacc025afa839181612cc8575b50612c96575090612c6f612b52565b6308c379a014612c86575b612c82612bde565b5090565b612c8e612b70565b15612c7a5790565b8051600019810191908211612cb457612cb09293506128eb565b5190565b634e487b7160e01b84526011600452602484fd5b612cdd9192503d8086833e6123a78183611368565b9038612c60565b90612d1592916040519163d06ca61f60e01b8352600483015260406024830152818060009586936044830190611451565b038173165c3410fc91ef562c50559f7d2289febed552d95afa839181612cc85750612c96575090612c6f612b52565b90612d7592916040519163d06ca61f60e01b8352600483015260406024830152818060009586936044830190611451565b038173eb45a3c4aedd0f47f345fb4c8a1802bb5740d7255afa839181612cc85750612c96575090612c6f612b52565b90612dd7939260405192839163d06ca61f60e01b8352600483015260406024830152818060009788956044830190611451565b03916001600160a01b03165afa839181612cc85750612c96575090612c6f612b52565b600090612e299260405193849283926307c0329d60e21b84526004840152604060248401526044830190611451565b03817398bf93ebf5c380c0e6ae8e192a7e2ae08edacc025afa60009181612e8d575b50612e845750612e59612b52565b6308c379a014612e72575b612e6c612bde565b50600090565b612e7a612b70565b15612e6457600090565b612cb0906128be565b612ea191923d8091833e6123a78183611368565b9038612e4b565b600090612ed79260405193849283926307c0329d60e21b84526004840152604060248401526044830190611451565b038173165c3410fc91ef562c50559f7d2289febed552d95afa60009181612e8d5750612e845750612e59612b52565b600090612f359260405193849283926307c0329d60e21b84526004840152604060248401526044830190611451565b038173eb45a3c4aedd0f47f345fb4c8a1802bb5740d7255afa60009181612e8d5750612e845750612e59612b52565b90600091612f95936040518095819482936307c0329d60e21b84526004840152604060248401526044830190611451565b03916001600160a01b03165afa60009181612e8d5750612e845750612e59612b52565b909192600093612fcc6060946000946128ff565b9190612fd88282612c0e565b91612fed612fe68284612ce4565b9185612d44565b9280151580613096575b613071575b5080151580613068575b613045575b50508015158061303c575b61301e575050565b73eb45a3c4aedd0f47f345fb4c8a1802bb5740d72595509093509150565b50838111613016565b73165c3410fc91ef562c50559f7d2289febed552d997509095509350388061300b565b50858111613006565b9650945095507398bf93ebf5c380c0e6ae8e192a7e2ae08edacc029580959438612ffc565b612ff756fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300a26469706673582212208658ee893e0e7f4f0d1c7c5ba12508a7cd40b2103a55e15ef7e0b13338729fb464736f6c63430008140033