ERC-20
Overview
Max Total Supply
97,486,837,500,000,000,000,000,000,000,428,609.0266475 WATER
Holders
271
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Water
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; /* ➜ Twitter: https://x.com/WaterNodeETH ➜ Gitbook: https://docs.waternode.io/ ➜ Website: https://waternode.io/ ➜ Portal: https://t.me/WaterNodeETH ➜ DAPP: https://app.waternode.io/ */ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "./interfaces/IRouter.sol"; import "./interfaces/IPair.sol"; import "./interfaces/IFactory.sol"; contract Water is ERC20, Ownable, ReentrancyGuard { // user data structure for storing nodes number, claiming rewards and cases bought struct UserData { uint nodesNumber; uint lastClaimTimestamp; uint[] boughtCasesIds; } bool public tokenCasesAllowed; // true if cases are allowed to be bought with token bool public ethCasesAllowed; // true if cases are allowed to be bought with eth bool swapping; // prevent fees / swapping when contract is already swapping tokens bool tokenLaunched; // is token already launched bool shouldBuyBack = true; // true if contract is automatically buying back bool shouldSellFees = true; // true if contract is automatically selling tokens fees uint public launchTimestamp; // contract launch timestamp in seconds uint public casesBought; // keep track of cases bought to have unique id per case uint public totalNodes; // number of nodes minted // contract parameters uint public nodesRewardsRate = 100_000; // rate of reward per day per node (in DECIMALS) (10%) uint public ethNodesDiscount = 50_000; // discount of buying a node with eth (in DECIMALS) (5%) uint public caseOpenDelay = 1; // block required for a case to be claimable uint public minSwapTokenAmount = 1e18; // minimum amount of token required to swap (sell fees) uint public minSwapEthAmount = 1e16; // minimum amount of eth required to swap (buy back) // contract constants uint public constant NODE_TOKEN_PRICE = 50e18; // fixed case price in WATER token uint private constant DECIMALS = 1_000_000; // base decimals amount used by the contract values uint private constant TOTAL_SUPPLY = 444_000e18; uint private constant LIMITS_PERIOD = 120; // time in seconds during which max wallet is active uint private constant MAX_WALLET_AMOUNT = (TOTAL_SUPPLY * 5) / 100; // maximum token per wallet during limits period (5%) uint private constant CLAIM_FEES = 50_000; // claim fees (in DECIMALS) (5%) // swap fees during each successive periods (high fees, then medium fees, then low fees) (in DECIMALS) (30% - 10% - 3%) uint private constant HIGH_FEES = 180_000; uint private constant MEDIUM_FEES = 100_000; uint private constant LOW_FEES = 30_000; uint private constant HIGH_FEES_PERIOD = 180; // 3 minutes duration uint private constant MEDIUM_FEES_PERIOD = 360; // 3 minutes duration address private constant BURN = 0x000000000000000000000000000000000000dEaD; address private immutable WETH; IRouter private immutable ROUTER; address public immutable pair; address payable public feesReceiver; mapping(address => UserData) public usersDatas; // store users data (nodes, claims, cases) mapping(uint => uint) public casesClaimableBlock; // minimum claimable block number per case id mapping(address => bool) public isFeesExempt; // store all fees exempted addresses event CaseBought(address indexed user, uint amount, bool inToken); event CaseOpened(address indexed user, uint nodesAmount); constructor(address _WETH, address _ROUTER) ERC20("WATER", "WATER") Ownable(msg.sender) { WETH = _WETH; ROUTER = IRouter(_ROUTER); pair = IFactory(ROUTER.factory()).createPair( address(this), WETH ); feesReceiver = payable(msg.sender); isFeesExempt[address(this)] = true; isFeesExempt[msg.sender] = true; uint teamSupply = TOTAL_SUPPLY / 10; _mint(address(this), TOTAL_SUPPLY - teamSupply); _mint(msg.sender, teamSupply); } /// @dev prevent fees / swapping during swap by the contract modifier Swapping() { swapping = true; _; swapping = false; } /// @dev add liquidity to the pool function launch() external payable onlyOwner Swapping { require(!tokenLaunched, "Token launched"); tokenLaunched = true; launchTimestamp = block.timestamp; uint liqAmount = (balanceOf(address(this)) * 85) / 100; _approve(address(this), address(ROUTER), liqAmount); ROUTER.addLiquidityETH{value: address(this).balance}(address(this), liqAmount, 0, 0, msg.sender, block.timestamp); } // CONTRACT PARAMETERS SETTER FUNCTIONS function setNumericParameter(uint _nodesRewardsRate, uint _caseOpenDelay, uint _ethNodesDiscount, uint _minSwapTokenAmount, uint _minSwapEthAmount) external onlyOwner { require(_nodesRewardsRate <= 300_000); // max 30% daily reward rate nodesRewardsRate = _nodesRewardsRate; require(_caseOpenDelay <= 30); // max 30 block delay after buy caseOpenDelay = _caseOpenDelay; require(_ethNodesDiscount <= 300_000); // max 30% eth discount ethNodesDiscount = _ethNodesDiscount; minSwapTokenAmount = _minSwapTokenAmount; minSwapEthAmount = _minSwapEthAmount; } function setContractSwaps(bool _shouldBuyBack, bool _shouldSellFees) external onlyOwner { shouldBuyBack = _shouldBuyBack; shouldSellFees = _shouldSellFees; } function setCasesAllowed(bool _tokenCases, bool _state) external onlyOwner { if (_tokenCases) tokenCasesAllowed = _state; else ethCasesAllowed = _state; } function setFeesExempted(address _account, bool _state) external onlyOwner { isFeesExempt[_account] = _state; } function setFeesReceiver(address _feesReceiver) external { require(feesReceiver == msg.sender); feesReceiver = payable(_feesReceiver); } /// @dev buy desired amount of cases with WATER tokens at a fixed price function buyCasesWater(uint _amount) external nonReentrant { require(tokenCasesAllowed, "Token cases disabled now"); uint price = NODE_TOKEN_PRICE * _amount; _burn(msg.sender, price); // burn 100% of the price _buyCases(_amount); emit CaseBought(msg.sender, _amount, true); } /// @dev buy desired amount of cases with etheureum at a fixed price function buyCasesETH(uint _amount) external payable nonReentrant { require(ethCasesAllowed, "ETH cases disabled now"); uint price = getCasePriceETH(_amount); require(msg.value >= price, "Not enough eth to pay"); uint feesToDev = (msg.value * 15) / 100; (bool sent, ) = feesReceiver.call{value: feesToDev}(""); require(sent); if (shouldBuyBack) _buyBack(); // buy back tokens with all ether amount of the contract (including the 85% of msg.value left) _buyCases(_amount); emit CaseBought(msg.sender, _amount, false); } /// @dev user version of _claimRewards with reentrancy guard function claimRewards() external nonReentrant { _claimRewards(msg.sender); } /// @dev directly buy nodes with rewards tokens (fees-free) (it is flooring the number of nodes) function compound() external nonReentrant { uint rewards = getNodesRewards(msg.sender); // do not apply claim fees here as it is a compound uint nodesAmount = rewards / NODE_TOKEN_PRICE; if (nodesAmount == 0) return; // if there is not enough reward to buy even 1 node, just return usersDatas[msg.sender].lastClaimTimestamp = block.timestamp; // set user rewards to 0 _mintNodes(msg.sender, nodesAmount, false); } /// @dev open all claimable cases, mint earned nodes + 1 per deprecated case and ignore unclaimable cases function openAllCases() external nonReentrant returns (uint nodesToMint) { uint maxBlockNumber = block.number; uint minBlockNumber = block.number - 256; address sender = msg.sender; uint i = 0; while (i < usersDatas[sender].boughtCasesIds.length) { uint caseId = usersDatas[sender].boughtCasesIds[i]; uint claimBlockNb = casesClaimableBlock[caseId]; // first case is that the case is either claimable or deprecated (but can't be claimable in the future) if (claimBlockNb < maxBlockNumber) { // if the case is claimable (within the bounds of cases claimability), mint node if (claimBlockNb > minBlockNumber) nodesToMint += _getCaseNodesNumber(claimBlockNb, caseId, sender); // else, the case is deprecated because of block number being too late (more or equal to 256 blocks after claiamble block), we mint 1 node else nodesToMint++; // for both case, we remove the case id from bought cases _removeFromBoughtCases(sender, i); } // else, it means the case is not claimable yet, it is saved (not deleted from boughtCases) and we pass to the next one else i++; } emit CaseOpened(msg.sender, nodesToMint); if (nodesToMint > 0) _mintNodes(msg.sender, nodesToMint, true); // mint nodes (rewarded / claimed + 1 node per deprecated cases) } /// @dev open one case using its index in bought cases list (mint 1 node if deprecated and revert if not claimable yet) function openCase(uint _boughtCasesIndex) external nonReentrant returns (uint nodesToMint) { uint caseId = usersDatas[msg.sender].boughtCasesIds[_boughtCasesIndex]; uint claimBlockNb = casesClaimableBlock[caseId]; require(claimBlockNb < block.number, "Not claimable yet"); _removeFromBoughtCases(msg.sender, _boughtCasesIndex); // if the case is claimable (within the bounds of cases claimability), mint nodes if (claimBlockNb > block.number - 256) nodesToMint = _getCaseNodesNumber(claimBlockNb, caseId, msg.sender); // else, the case is deprecated because of block number being too late, we mint 1 node else nodesToMint = 1; emit CaseOpened(msg.sender, nodesToMint); _mintNodes(msg.sender, nodesToMint, true); } /// @dev internal function managing core operation for buying cases (not the payment) function _buyCases(uint _amount) private { uint claimableBlock = block.number + caseOpenDelay; // claimable block of all cases bought during this tx for (uint i = 0; i < _amount; i++) { usersDatas[msg.sender].boughtCasesIds.push(casesBought); casesClaimableBlock[casesBought] = claimableBlock; casesBought++; } } /// @dev internal function managing core operation for minting nodes function _mintNodes(address _account, uint _amount, bool _doClaimRewards) private { if (_doClaimRewards) _claimRewards(_account); totalNodes += _amount; usersDatas[_account].nodesNumber += _amount; } /// @dev claim rewards from node function _claimRewards(address _account) private { uint rewards = getNodesRewards(_account); uint fees = (rewards * CLAIM_FEES) / DECIMALS; // get total fees from claiming if (rewards != 0) { _mint(_account, rewards - fees); // mint rewards to the user with fees incurred _mint(address(this), fees / 2); // half of the fees go into this contract for the devs // the other half of the fees is being burned (<=> not minted) } usersDatas[_account].lastClaimTimestamp = block.timestamp; } function _removeFromBoughtCases(address _account, uint _id) internal { usersDatas[_account].boughtCasesIds[_id] = usersDatas[_account].boughtCasesIds[usersDatas[_account].boughtCasesIds.length - 1]; usersDatas[_account].boughtCasesIds.pop(); } function _getCaseNodesNumber(uint _claimBlockNb, uint _caseId, address _sender) private view returns (uint) { uint seed = (uint(keccak256(abi.encodePacked(blockhash(_claimBlockNb), _caseId, _sender))) % 100) + 1; if (seed <= 5) return 3; if (seed <= 20) return 2; return 1; } /// @dev get current total rewards (no fees included) function getNodesRewards(address _account) public view returns (uint) { uint nodesNumber = usersDatas[_account].nodesNumber; uint lastClaimTimestamp = usersDatas[_account].lastClaimTimestamp; uint totalTokensInNodes = NODE_TOKEN_PRICE * nodesNumber; uint rewardsPercentage = ((block.timestamp - lastClaimTimestamp) * nodesRewardsRate) / 1 days; // percentage of rewards of the total tokens (IN DECIMALS) return (totalTokensInNodes * rewardsPercentage) / DECIMALS; } /// @dev return the price in eth (wei) to buy an amount of cases (with a discount) function getCasePriceETH(uint _amount) public view returns (uint) { uint discountMultiplier = DECIMALS - ethNodesDiscount; (uint reserve0, uint reserve1, ) = IPair(pair).getReserves(); require(reserve0 > 0 && reserve1 > 0, "No reserve"); if (IPair(pair).token0() != WETH) (reserve0, reserve1) = (reserve1, reserve0); uint tokenPriceWEI = (reserve0 * 1e18) / reserve1; require(tokenPriceWEI != 0, "Invalid price"); uint nodeFullPriceWEI = (NODE_TOKEN_PRICE * tokenPriceWEI) / 1e18; uint finalPrice = (nodeFullPriceWEI * discountMultiplier) / DECIMALS; return finalPrice * _amount; } function getOwnedCases(address _account) external view returns (uint[] memory) { return usersDatas[_account].boughtCasesIds; } /// @dev buy back tokens with contract balance function _buyBack() internal Swapping { if (address(this).balance < minSwapEthAmount) return; address[] memory path = new address[](2); path[0] = WETH; path[1] = address(this); ROUTER.swapExactETHForTokensSupportingFeeOnTransferTokens{value: address(this).balance}( 0, path, BURN, block.timestamp + 1 ); _burn(BURN, balanceOf(BURN)); // burn all tokens received by BURN address } /// @dev sell tokens fees in the contract for eth function _sellFees(uint maxAmount) internal Swapping { uint256 balance = min(maxAmount, balanceOf(address(this))); if (balance < minSwapTokenAmount) return; address[] memory path = new address[](2); path[0] = address(this); path[1] = WETH; _approve(address(this), address(ROUTER), type(uint256).max, false); ROUTER.swapExactTokensForETHSupportingFeeOnTransferTokens( balance, 0, path, feesReceiver, block.timestamp ); } /// @dev retreive eth or tokens funds (so in case buy back or sell fees are desactivated for any reasons, funds are not lost) function retreiveFunds(bool _eth) external onlyOwner Swapping { require(!shouldBuyBack || !shouldSellFees); if (_eth) { (bool sent, ) = feesReceiver.call{value: address(this).balance}(""); require(sent); } else { transfer(feesReceiver, balanceOf(address(this))); } } /// @dev refund nodes from potential issues / offer some giveaway function awardNodes(address _account, uint _amount, bool _doClaimRewards) external onlyOwner { _mintNodes(_account, _amount, _doClaimRewards); } function _update(address from, address to, uint256 value) internal override { if (isFeesExempt[from] || isFeesExempt[to] || swapping) return super._update(from, to, value); // take fees if it is a swap bool takeFees = from == pair || to == pair; uint fees = takeFees ? (value * getFees()) / DECIMALS : 0; if (fees > 0) super._update(from, address(this), fees); value -= fees; // check for limits if (limitsActive() && to != pair && to != address(ROUTER)) { require(balanceOf(to) + value <= MAX_WALLET_AMOUNT, "Maximum token per wallet reached"); } // sell fees if (shouldSellFees && from != pair) _sellFees(value); super._update(from, to, value); } function getFees() private view returns (uint) { uint elapsed = block.timestamp - launchTimestamp; if (elapsed > MEDIUM_FEES_PERIOD) return LOW_FEES; if (elapsed > HIGH_FEES_PERIOD) return MEDIUM_FEES; return HIGH_FEES; } function limitsActive() private view returns (bool) { return block.timestamp - launchTimestamp <= LIMITS_PERIOD; } function min(uint a, uint b) private pure returns (uint) { return a < b ? a : b; } receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * 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 Ownable is Context { address private _owner; /** * @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. */ constructor(address initialOwner) { 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) { 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 { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; interface IFactory { function createPair( address tokenA, address tokenB ) external returns (address pair); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; interface IPair { function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; interface IRouter { function factory() external pure returns (address); function WETH() external pure returns (address); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function swapExactTokensForETHSupportingFeeOnTransferTokens( 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 addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_ROUTER","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inToken","type":"bool"}],"name":"CaseBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"nodesAmount","type":"uint256"}],"name":"CaseOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"NODE_TOKEN_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_doClaimRewards","type":"bool"}],"name":"awardNodes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"buyCasesETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"buyCasesWater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"caseOpenDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"casesBought","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"casesClaimableBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"compound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethCasesAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethNodesDiscount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesReceiver","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getCasePriceETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getNodesRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getOwnedCases","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isFeesExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"launchTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSwapEthAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSwapTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nodesRewardsRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openAllCases","outputs":[{"internalType":"uint256","name":"nodesToMint","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_boughtCasesIndex","type":"uint256"}],"name":"openCase","outputs":[{"internalType":"uint256","name":"nodesToMint","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_eth","type":"bool"}],"name":"retreiveFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_tokenCases","type":"bool"},{"internalType":"bool","name":"_state","type":"bool"}],"name":"setCasesAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldBuyBack","type":"bool"},{"internalType":"bool","name":"_shouldSellFees","type":"bool"}],"name":"setContractSwaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_state","type":"bool"}],"name":"setFeesExempted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feesReceiver","type":"address"}],"name":"setFeesReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nodesRewardsRate","type":"uint256"},{"internalType":"uint256","name":"_caseOpenDelay","type":"uint256"},{"internalType":"uint256","name":"_ethNodesDiscount","type":"uint256"},{"internalType":"uint256","name":"_minSwapTokenAmount","type":"uint256"},{"internalType":"uint256","name":"_minSwapEthAmount","type":"uint256"}],"name":"setNumericParameter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCasesAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNodes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usersDatas","outputs":[{"internalType":"uint256","name":"nodesNumber","type":"uint256"},{"internalType":"uint256","name":"lastClaimTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040526001600760046101000a81548160ff0219169083151502179055506001600760056101000a81548160ff021916908315150217905550620186a0600b5561c350600c556001600d55670de0b6b3a7640000600e55662386f26fc10000600f553480156200007057600080fd5b5060405162005eef38038062005eef8339818101604052810190620000969190620010be565b336040518060400160405280600581526020017f57415445520000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f574154455200000000000000000000000000000000000000000000000000000081525081600390816200011491906200137f565b5080600490816200012691906200137f565b505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200019e5760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040162000195919062001477565b60405180910390fd5b620001af816200049d60201b60201c565b5060016006819055508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505060a05173ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000294919062001494565b73ffffffffffffffffffffffffffffffffffffffff1663c9c65396306080516040518363ffffffff1660e01b8152600401620002d2929190620014c6565b6020604051808303816000875af1158015620002f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000318919062001494565b73ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff168152505033601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001601360003073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001601360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600a695e0549c9632e1d80000062000457919062001551565b9050620004823082695e0549c9632e1d80000062000476919062001589565b6200056360201b60201c565b6200049433826200056360201b60201c565b5050506200193d565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620005d85760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401620005cf919062001477565b60405180910390fd5b620005ec60008383620005f060201b60201c565b5050565b601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680620006925750601360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b80620006aa5750600760029054906101000a900460ff165b15620006c957620006c38383836200093960201b60201c565b62000934565b600060c05173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148062000735575060c05173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b90506000816200074757600062000775565b620f42406200075b62000b6960201b60201c565b84620007689190620015c4565b62000774919062001551565b5b905060008111156200079557620007948530836200093960201b60201c565b5b8083620007a3919062001589565b9250620007b562000bb760201b60201c565b8015620007f0575060c05173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b80156200082b575060a05173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15620008bb5760646005695e0549c9632e1d8000006200084c9190620015c4565b62000858919062001551565b836200086a8662000bd260201b60201c565b6200087691906200160f565b1115620008ba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620008b190620016ab565b60405180910390fd5b5b600760059054906101000a900460ff16801562000906575060c05173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156200091e576200091d8362000c1a60201b60201c565b5b620009318585856200093960201b60201c565b50505b505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036200098f5780600260008282546200098291906200160f565b9250508190555062000a65565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101562000a1e578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040162000a1593929190620016de565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000ab0578060026000828254039250508190555062000afd565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405162000b5c91906200171b565b60405180910390a3505050565b6000806008544262000b7c919062001589565b905061016881111562000b955761753091505062000bb4565b60b481111562000bac57620186a091505062000bb4565b6202bf209150505b90565b600060786008544262000bcb919062001589565b1115905090565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6001600760026101000a81548160ff021916908315150217905550600062000c598262000c4d3062000bd260201b60201c565b62000e5960201b60201c565b9050600e5481101562000c6d575062000e3b565b6000600267ffffffffffffffff81111562000c8d5762000c8c62001110565b5b60405190808252806020026020018201604052801562000cbc5781602001602082028036833780820191505090505b509050308160008151811062000cd75762000cd662001738565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506080518160018151811062000d2b5762000d2a62001738565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505062000d9c3060a0517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600062000e7460201b60201c565b60a05173ffffffffffffffffffffffffffffffffffffffff1663791ac94783600084601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16426040518663ffffffff1660e01b815260040162000e04959493929190620018d9565b600060405180830381600087803b15801562000e1f57600080fd5b505af115801562000e34573d6000803e3d6000fd5b5050505050505b6000600760026101000a81548160ff02191690831515021790555050565b600081831062000e6a578162000e6c565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160362000ee95760006040517fe602df0500000000000000000000000000000000000000000000000000000000815260040162000ee0919062001477565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000f5e5760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040162000f55919062001477565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156200104e578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516200104591906200171b565b60405180910390a35b50505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620010868262001059565b9050919050565b620010988162001079565b8114620010a457600080fd5b50565b600081519050620010b8816200108d565b92915050565b60008060408385031215620010d857620010d762001054565b5b6000620010e885828601620010a7565b9250506020620010fb85828601620010a7565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200118757607f821691505b6020821081036200119d576200119c6200113f565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620012077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620011c8565b620012138683620011c8565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620012606200125a62001254846200122b565b62001235565b6200122b565b9050919050565b6000819050919050565b6200127c836200123f565b620012946200128b8262001267565b848454620011d5565b825550505050565b600090565b620012ab6200129c565b620012b881848462001271565b505050565b5b81811015620012e057620012d4600082620012a1565b600181019050620012be565b5050565b601f8211156200132f57620012f981620011a3565b6200130484620011b8565b8101602085101562001314578190505b6200132c6200132385620011b8565b830182620012bd565b50505b505050565b600082821c905092915050565b6000620013546000198460080262001334565b1980831691505092915050565b60006200136f838362001341565b9150826002028217905092915050565b6200138a8262001105565b67ffffffffffffffff811115620013a657620013a562001110565b5b620013b282546200116e565b620013bf828285620012e4565b600060209050601f831160018114620013f75760008415620013e2578287015190505b620013ee858262001361565b8655506200145e565b601f1984166200140786620011a3565b60005b8281101562001431578489015182556001820191506020850194506020810190506200140a565b868310156200145157848901516200144d601f89168262001341565b8355505b6001600288020188555050505b505050505050565b620014718162001079565b82525050565b60006020820190506200148e600083018462001466565b92915050565b600060208284031215620014ad57620014ac62001054565b5b6000620014bd84828501620010a7565b91505092915050565b6000604082019050620014dd600083018562001466565b620014ec602083018462001466565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200155e826200122b565b91506200156b836200122b565b9250826200157e576200157d620014f3565b5b828204905092915050565b600062001596826200122b565b9150620015a3836200122b565b9250828203905081811115620015be57620015bd62001522565b5b92915050565b6000620015d1826200122b565b9150620015de836200122b565b9250828202620015ee816200122b565b9150828204841483151762001608576200160762001522565b5b5092915050565b60006200161c826200122b565b915062001629836200122b565b925082820190508082111562001644576200164362001522565b5b92915050565b600082825260208201905092915050565b7f4d6178696d756d20746f6b656e207065722077616c6c65742072656163686564600082015250565b6000620016936020836200164a565b9150620016a0826200165b565b602082019050919050565b60006020820190508181036000830152620016c68162001684565b9050919050565b620016d8816200122b565b82525050565b6000606082019050620016f5600083018662001466565b620017046020830185620016cd565b620017136040830184620016cd565b949350505050565b6000602082019050620017326000830184620016cd565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000819050919050565b6000620017926200178c620017868462001767565b62001235565b6200122b565b9050919050565b620017a48162001771565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b620017e18162001079565b82525050565b6000620017f58383620017d6565b60208301905092915050565b6000602082019050919050565b60006200181b82620017aa565b620018278185620017b5565b93506200183483620017c6565b8060005b838110156200186b5781516200184f8882620017e7565b97506200185c8362001801565b92505060018101905062001838565b5085935050505092915050565b600062001899620018936200188d8462001059565b62001235565b62001059565b9050919050565b6000620018ad8262001878565b9050919050565b6000620018c182620018a0565b9050919050565b620018d381620018b4565b82525050565b600060a082019050620018f06000830188620016cd565b620018ff602083018762001799565b81810360408301526200191381866200180e565b9050620019246060830185620018c8565b620019336080830184620016cd565b9695505050505050565b60805160a05160c051614527620019c8600039600081816115b7015281816116f1015281816119cb01528181612b2c01528181612b8101528181612c370152612d75015260008181610b2c01528181610b53015281816120d501528181612c8f01528181613241015261328a0152600081816116ba0152818161201701526131ce01526145276000f3fe6080604052600436106102765760003560e01c80637ab18aad1161014f578063bca93cf5116100c1578063df5fef921161007a578063df5fef9214610984578063ead267e7146109ad578063f18e7951146109d8578063f2fde38b14610a01578063f69e204614610a2a578063f906b61814610a415761027d565b8063bca93cf514610850578063c40d24b21461087b578063c92f69a9146108b8578063cc66ccea146108e1578063d58a90a71461091e578063dd62ed3e146109475761027d565b80639592d424116101135780639592d4241461072a57806395d89b4114610755578063a8aa1b3114610780578063a9059cbb146107ab578063aa3164c4146107e8578063b865e5d9146108255761027d565b80637ab18aad1461061c5780637d6731701461065a578063846f299e146106855780638da5cb5b146106c2578063946da64e146106ed5761027d565b8063328881df116101e85780635055c413116101ac5780635055c4131461051c5780636182d05d1461054757806365cf7c9b1461057257806367c7f5951461059d57806370a08231146105c8578063715018a6146106055761027d565b8063328881df1461045d5780633688555614610486578063372500ab146104af5780633c6ece75146104c6578063489f91d6146104f15761027d565b806317ed9d9d1161023a57806317ed9d9d1461033957806318160ddd146103645780631ae483b61461038f5780632073b17c146103b857806323b872dd146103f5578063313ce567146104325761027d565b806301339c211461028257806302f729b81461028c57806306fdde03146102b5578063095ea7b3146102e05780630c7c5c2a1461031d5761027d565b3661027d57005b600080fd5b61028a610a6c565b005b34801561029857600080fd5b506102b360048036038101906102ae91906133b3565b610c1a565b005b3480156102c157600080fd5b506102ca610c7a565b6040516102d791906134be565b60405180910390f35b3480156102ec57600080fd5b506103076004803603810190610302919061353e565b610d0c565b6040516103149190613599565b60405180910390f35b610337600480360381019061033291906135b4565b610d2f565b005b34801561034557600080fd5b5061034e610f11565b60405161035b91906135f0565b60405180910390f35b34801561037057600080fd5b50610379610f1e565b60405161038691906135f0565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b19190613637565b610f28565b005b3480156103c457600080fd5b506103df60048036038101906103da91906135b4565b611075565b6040516103ec91906135f0565b60405180910390f35b34801561040157600080fd5b5061041c60048036038101906104179190613664565b6111db565b6040516104299190613599565b60405180910390f35b34801561043e57600080fd5b5061044761120a565b60405161045491906136d3565b60405180910390f35b34801561046957600080fd5b50610484600480360381019061047f91906136ee565b611213565b005b34801561049257600080fd5b506104ad60048036038101906104a891906135b4565b61122b565b005b3480156104bb57600080fd5b506104c461130b565b005b3480156104d257600080fd5b506104db611326565b6040516104e891906135f0565b60405180910390f35b3480156104fd57600080fd5b5061050661132c565b60405161051391906135f0565b60405180910390f35b34801561052857600080fd5b50610531611332565b60405161053e9190613599565b60405180910390f35b34801561055357600080fd5b5061055c611345565b60405161056991906135f0565b60405180910390f35b34801561057e57600080fd5b5061058761150a565b60405161059491906135f0565b60405180910390f35b3480156105a957600080fd5b506105b2611510565b6040516105bf91906135f0565b60405180910390f35b3480156105d457600080fd5b506105ef60048036038101906105ea9190613741565b611516565b6040516105fc91906135f0565b60405180910390f35b34801561061157600080fd5b5061061a61155e565b005b34801561062857600080fd5b50610643600480360381019061063e9190613741565b611572565b60405161065192919061376e565b60405180910390f35b34801561066657600080fd5b5061066f611596565b60405161067c91906135f0565b60405180910390f35b34801561069157600080fd5b506106ac60048036038101906106a791906135b4565b61159c565b6040516106b991906135f0565b60405180910390f35b3480156106ce57600080fd5b506106d761186d565b6040516106e491906137a6565b60405180910390f35b3480156106f957600080fd5b50610714600480360381019061070f9190613741565b611897565b604051610721919061387f565b60405180910390f35b34801561073657600080fd5b5061073f611931565b60405161074c91906135f0565b60405180910390f35b34801561076157600080fd5b5061076a611937565b60405161077791906134be565b60405180910390f35b34801561078c57600080fd5b506107956119c9565b6040516107a291906137a6565b60405180910390f35b3480156107b757600080fd5b506107d260048036038101906107cd919061353e565b6119ed565b6040516107df9190613599565b60405180910390f35b3480156107f457600080fd5b5061080f600480360381019061080a91906135b4565b611a10565b60405161081c91906135f0565b60405180910390f35b34801561083157600080fd5b5061083a611a28565b60405161084791906135f0565b60405180910390f35b34801561085c57600080fd5b50610865611a2e565b60405161087291906138c2565b60405180910390f35b34801561088757600080fd5b506108a2600480360381019061089d9190613741565b611a54565b6040516108af9190613599565b60405180910390f35b3480156108c457600080fd5b506108df60048036038101906108da91906138dd565b611a74565b005b3480156108ed57600080fd5b5061090860048036038101906109039190613741565b611ad7565b60405161091591906135f0565b60405180910390f35b34801561092a57600080fd5b506109456004803603810190610940919061391d565b611bcf565b005b34801561095357600080fd5b5061096e6004803603810190610969919061395d565b611c0f565b60405161097b91906135f0565b60405180910390f35b34801561099057600080fd5b506109ab60048036038101906109a6919061391d565b611c96565b005b3480156109b957600080fd5b506109c2611ce2565b6040516109cf91906135f0565b60405180910390f35b3480156109e457600080fd5b506109ff60048036038101906109fa9190613741565b611ce8565b005b348015610a0d57600080fd5b50610a286004803603810190610a239190613741565b611d86565b005b348015610a3657600080fd5b50610a3f611e0c565b005b348015610a4d57600080fd5b50610a56611ea9565b604051610a639190613599565b60405180910390f35b610a74611ebc565b6001600760026101000a81548160ff021916908315150217905550600760039054906101000a900460ff1615610adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad6906139e9565b60405180910390fd5b6001600760036101000a81548160ff02191690831515021790555042600881905550600060646055610b1030611516565b610b1a9190613a38565b610b249190613aa9565b9050610b51307f000000000000000000000000000000000000000000000000000000000000000083611f43565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f305d71947308460008033426040518863ffffffff1660e01b8152600401610bb696959493929190613b1f565b60606040518083038185885af1158015610bd4573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610bf99190613b95565b505050506000600760026101000a81548160ff021916908315150217905550565b610c22611ebc565b620493e0851115610c3257600080fd5b84600b81905550601e841115610c4757600080fd5b83600d81905550620493e0831115610c5e57600080fd5b82600c8190555081600e8190555080600f819055505050505050565b606060038054610c8990613c17565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb590613c17565b8015610d025780601f10610cd757610100808354040283529160200191610d02565b820191906000526020600020905b815481529060010190602001808311610ce557829003601f168201915b5050505050905090565b600080610d17611f55565b9050610d24818585611f43565b600191505092915050565b610d37611f5d565b600760019054906101000a900460ff16610d86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7d90613c94565b60405180910390fd5b6000610d918261159c565b905080341015610dd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcd90613d00565b60405180910390fd5b60006064600f34610de79190613a38565b610df19190613aa9565b90506000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682604051610e3b90613d51565b60006040518083038185875af1925050503d8060008114610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b5050905080610e8b57600080fd5b600760049054906101000a900460ff1615610ea957610ea8611fa3565b5b610eb2846121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c7716856000604051610efb929190613d66565b60405180910390a2505050610f0e61227b565b50565b6802b5e3af16b188000081565b6000600254905090565b610f30611ebc565b6001600760026101000a81548160ff021916908315150217905550600760049054906101000a900460ff161580610f745750600760059054906101000a900460ff16155b610f7d57600080fd5b8015611021576000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1647604051610fcb90613d51565b60006040518083038185875af1925050503d8060008114611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b505090508061101b57600080fd5b50611057565b611055601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661105030611516565b6119ed565b505b6000600760026101000a81548160ff02191690831515021790555050565b600061107f611f5d565b6000601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020183815481106110d5576110d4613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905043811061113c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113390613e0a565b60405180910390fd5b6111463385612285565b610100436111549190613e2a565b81111561116d57611166818333612403565b9250611172565b600192505b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc846040516111b891906135f0565b60405180910390a26111cc33846001612480565b50506111d661227b565b919050565b6000806111e6611f55565b90506111f3858285612507565b6111fe85858561259b565b60019150509392505050565b60006012905090565b61121b611ebc565b611226838383612480565b505050565b611233611f5d565b600760009054906101000a900460ff16611282576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127990613eaa565b60405180910390fd5b6000816802b5e3af16b18800006112999190613a38565b90506112a5338261268f565b6112ae826121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c77168360016040516112f7929190613d66565b60405180910390a25061130861227b565b50565b611313611f5d565b61131c33612711565b61132461227b565b565b600f5481565b60095481565b600760019054906101000a900460ff1681565b600061134f611f5d565b60004390506000610100436113649190613e2a565b9050600033905060005b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180549050811015611497576000601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061141157611410613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905085811015611481578481111561146357611451818386612403565b8761145c9190613eca565b9650611472565b868061146e90613efe565b9750505b61147c8484612285565b611490565b828061148c90613efe565b9350505b505061136e565b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc866040516114dd91906135f0565b60405180910390a260008511156114fb576114fa33866001612480565b5b5050505061150761227b565b90565b60085481565b600c5481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611566611ebc565b61157060006127be565b565b60116020528060005260406000206000915090508060000154908060010154905082565b600e5481565b600080600c54620f42406115b09190613e2a565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190613fc8565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156116795750600081115b6116b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116af90614067565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177e919061409c565b73ffffffffffffffffffffffffffffffffffffffff16146117a457808280925081935050505b600081670de0b6b3a7640000846117bb9190613a38565b6117c59190613aa9565b90506000810361180a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180190614115565b60405180910390fd5b6000670de0b6b3a7640000826802b5e3af16b188000061182a9190613a38565b6118349190613aa9565b90506000620f424086836118489190613a38565b6118529190613aa9565b905087816118609190613a38565b9650505050505050919050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180548060200260200160405190810160405280929190818152602001828054801561192557602002820191906000526020600020905b815481526020019060010190808311611911575b50505050509050919050565b600a5481565b60606004805461194690613c17565b80601f016020809104026020016040519081016040528092919081815260200182805461197290613c17565b80156119bf5780601f10611994576101008083540402835291602001916119bf565b820191906000526020600020905b8154815290600101906020018083116119a257829003601f168201915b5050505050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806119f8611f55565b9050611a0581858561259b565b600191505092915050565b60126020528060005260406000206000915090505481565b600d5481565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60136020528060005260406000206000915054906101000a900460ff1681565b611a7c611ebc565b80601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600080601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015490506000826802b5e3af16b1880000611b7d9190613a38565b9050600062015180600b548442611b949190613e2a565b611b9e9190613a38565b611ba89190613aa9565b9050620f42408183611bba9190613a38565b611bc49190613aa9565b945050505050919050565b611bd7611ebc565b81600760046101000a81548160ff02191690831515021790555080600760056101000a81548160ff0219169083151502179055505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611c9e611ebc565b8115611cc35780600760006101000a81548160ff021916908315150217905550611cde565b80600760016101000a81548160ff0219169083151502179055505b5050565b600b5481565b3373ffffffffffffffffffffffffffffffffffffffff16601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d4257600080fd5b80601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611d8e611ebc565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e005760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611df791906137a6565b60405180910390fd5b611e09816127be565b50565b611e14611f5d565b6000611e1f33611ad7565b905060006802b5e3af16b188000082611e389190613aa9565b905060008103611e49575050611e9f565b42601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550611e9c33826000612480565b50505b611ea761227b565b565b600760009054906101000a900460ff1681565b611ec4611f55565b73ffffffffffffffffffffffffffffffffffffffff16611ee261186d565b73ffffffffffffffffffffffffffffffffffffffff1614611f4157611f05611f55565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611f3891906137a6565b60405180910390fd5b565b611f508383836001612884565b505050565b600033905090565b600260065403611f99576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600681905550565b6001600760026101000a81548160ff021916908315150217905550600f54471061218c576000600267ffffffffffffffff811115611fe457611fe3614135565b5b6040519080825280602002602001820160405280156120125781602001602082028036833780820191505090505b5090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061204a57612049613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050308160018151811061209957612098613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b6f9de954760008461dead6001426121239190613eca565b6040518663ffffffff1660e01b81526004016121429493929190614222565b6000604051808303818588803b15801561215b57600080fd5b505af115801561216f573d6000803e3d6000fd5b505050505061218a61dead61218561dead611516565b61268f565b505b6000600760026101000a81548160ff021916908315150217905550565b6000600d54436121b99190613eca565b905060005b8281101561227657601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201600954908060018154018082558091505060019003906000526020600020016000909190919091505581601260006009548152602001908152602001600020819055506009600081548092919061225e90613efe565b9190505550808061226e90613efe565b9150506121be565b505050565b6001600681905550565b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002016001601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201805490506123199190613e2a565b8154811061232a57612329613d8f565b5b9060005260206000200154601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061238957612388613d8f565b5b9060005260206000200181905550601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018054806123e9576123e861426e565b5b600190038181906000526020600020016000905590555050565b600080600160648640868660405160200161242093929190614331565b6040516020818303038152906040528051906020012060001c612443919061436e565b61244d9190613eca565b905060058111612461576003915050612479565b60148111612473576002915050612479565b60019150505b9392505050565b80156124905761248f83612711565b5b81600a60008282546124a29190613eca565b9250508190555081601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546124fb9190613eca565b92505081905550505050565b60006125138484611c0f565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146125955781811015612585578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161257c9392919061439f565b60405180910390fd5b61259484848484036000612884565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361260d5760006040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260040161260491906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361267f5760006040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161267691906137a6565b60405180910390fd5b61268a838383612a5b565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036127015760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016126f891906137a6565b60405180910390fd5b61270d82600083612a5b565b5050565b600061271c82611ad7565b90506000620f424061c350836127329190613a38565b61273c9190613aa9565b9050600082146127725761275b8382846127569190613e2a565b612de6565b6127713060028361276c9190613aa9565b612de6565b5b42601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036128f65760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016128ed91906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129685760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161295f91906137a6565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612a55578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a4c91906135f0565b60405180910390a35b50505050565b601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680612afc5750601360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b80612b135750600760029054906101000a900460ff165b15612b2857612b23838383612e68565b612de1565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612bcf57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b9050600081612bdf576000612c01565b620f4240612beb61308d565b84612bf69190613a38565b612c009190613aa9565b5b90506000811115612c1857612c17853083612e68565b5b8083612c249190613e2a565b9250612c2e6130d5565b8015612c8657507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b8015612cde57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15612d5c5760646005695e0549c9632e1d800000612cfc9190613a38565b612d069190613aa9565b83612d1086611516565b612d1a9190613eca565b1115612d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d5290614422565b60405180910390fd5b5b600760059054906101000a900460ff168015612dc457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15612dd357612dd2836130ee565b5b612dde858585612e68565b50505b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e585760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612e4f91906137a6565b60405180910390fd5b612e6460008383612a5b565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612eba578060026000828254612eae9190613eca565b92505081905550612f8d565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612f46578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612f3d9392919061439f565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612fd65780600260008282540392505081905550613023565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161308091906135f0565b60405180910390a3505050565b6000806008544261309e9190613e2a565b90506101688111156130b5576175309150506130d2565b60b48111156130ca57620186a09150506130d2565b6202bf209150505b90565b60006078600854426130e79190613e2a565b1115905090565b6001600760026101000a81548160ff021916908315150217905550600061311d8261311830611516565b61335f565b9050600e5481101561312f5750613341565b6000600267ffffffffffffffff81111561314c5761314b614135565b5b60405190808252806020026020018201604052801561317a5781602001602082028036833780820191505090505b509050308160008151811061319257613191613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f00000000000000000000000000000000000000000000000000000000000000008160018151811061320157613200613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050613288307f00000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000612884565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663791ac94783600084601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16426040518663ffffffff1660e01b815260040161330c959493929190614497565b600060405180830381600087803b15801561332657600080fd5b505af115801561333a573d6000803e3d6000fd5b5050505050505b6000600760026101000a81548160ff02191690831515021790555050565b600081831061336e5781613370565b825b905092915050565b600080fd5b6000819050919050565b6133908161337d565b811461339b57600080fd5b50565b6000813590506133ad81613387565b92915050565b600080600080600060a086880312156133cf576133ce613378565b5b60006133dd8882890161339e565b95505060206133ee8882890161339e565b94505060406133ff8882890161339e565b93505060606134108882890161339e565b92505060806134218882890161339e565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346857808201518184015260208101905061344d565b60008484015250505050565b6000601f19601f8301169050919050565b60006134908261342e565b61349a8185613439565b93506134aa81856020860161344a565b6134b381613474565b840191505092915050565b600060208201905081810360008301526134d88184613485565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061350b826134e0565b9050919050565b61351b81613500565b811461352657600080fd5b50565b60008135905061353881613512565b92915050565b6000806040838503121561355557613554613378565b5b600061356385828601613529565b92505060206135748582860161339e565b9150509250929050565b60008115159050919050565b6135938161357e565b82525050565b60006020820190506135ae600083018461358a565b92915050565b6000602082840312156135ca576135c9613378565b5b60006135d88482850161339e565b91505092915050565b6135ea8161337d565b82525050565b600060208201905061360560008301846135e1565b92915050565b6136148161357e565b811461361f57600080fd5b50565b6000813590506136318161360b565b92915050565b60006020828403121561364d5761364c613378565b5b600061365b84828501613622565b91505092915050565b60008060006060848603121561367d5761367c613378565b5b600061368b86828701613529565b935050602061369c86828701613529565b92505060406136ad8682870161339e565b9150509250925092565b600060ff82169050919050565b6136cd816136b7565b82525050565b60006020820190506136e860008301846136c4565b92915050565b60008060006060848603121561370757613706613378565b5b600061371586828701613529565b93505060206137268682870161339e565b925050604061373786828701613622565b9150509250925092565b60006020828403121561375757613756613378565b5b600061376584828501613529565b91505092915050565b600060408201905061378360008301856135e1565b61379060208301846135e1565b9392505050565b6137a081613500565b82525050565b60006020820190506137bb6000830184613797565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137f68161337d565b82525050565b600061380883836137ed565b60208301905092915050565b6000602082019050919050565b600061382c826137c1565b61383681856137cc565b9350613841836137dd565b8060005b8381101561387257815161385988826137fc565b975061386483613814565b925050600181019050613845565b5085935050505092915050565b600060208201905081810360008301526138998184613821565b905092915050565b60006138ac826134e0565b9050919050565b6138bc816138a1565b82525050565b60006020820190506138d760008301846138b3565b92915050565b600080604083850312156138f4576138f3613378565b5b600061390285828601613529565b925050602061391385828601613622565b9150509250929050565b6000806040838503121561393457613933613378565b5b600061394285828601613622565b925050602061395385828601613622565b9150509250929050565b6000806040838503121561397457613973613378565b5b600061398285828601613529565b925050602061399385828601613529565b9150509250929050565b7f546f6b656e206c61756e63686564000000000000000000000000000000000000600082015250565b60006139d3600e83613439565b91506139de8261399d565b602082019050919050565b60006020820190508181036000830152613a02816139c6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a438261337d565b9150613a4e8361337d565b9250828202613a5c8161337d565b91508282048414831517613a7357613a72613a09565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613ab48261337d565b9150613abf8361337d565b925082613acf57613ace613a7a565b5b828204905092915050565b6000819050919050565b6000819050919050565b6000613b09613b04613aff84613ada565b613ae4565b61337d565b9050919050565b613b1981613aee565b82525050565b600060c082019050613b346000830189613797565b613b4160208301886135e1565b613b4e6040830187613b10565b613b5b6060830186613b10565b613b686080830185613797565b613b7560a08301846135e1565b979650505050505050565b600081519050613b8f81613387565b92915050565b600080600060608486031215613bae57613bad613378565b5b6000613bbc86828701613b80565b9350506020613bcd86828701613b80565b9250506040613bde86828701613b80565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c2f57607f821691505b602082108103613c4257613c41613be8565b5b50919050565b7f4554482063617365732064697361626c6564206e6f7700000000000000000000600082015250565b6000613c7e601683613439565b9150613c8982613c48565b602082019050919050565b60006020820190508181036000830152613cad81613c71565b9050919050565b7f4e6f7420656e6f7567682065746820746f207061790000000000000000000000600082015250565b6000613cea601583613439565b9150613cf582613cb4565b602082019050919050565b60006020820190508181036000830152613d1981613cdd565b9050919050565b600081905092915050565b50565b6000613d3b600083613d20565b9150613d4682613d2b565b600082019050919050565b6000613d5c82613d2e565b9150819050919050565b6000604082019050613d7b60008301856135e1565b613d88602083018461358a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e6f7420636c61696d61626c6520796574000000000000000000000000000000600082015250565b6000613df4601183613439565b9150613dff82613dbe565b602082019050919050565b60006020820190508181036000830152613e2381613de7565b9050919050565b6000613e358261337d565b9150613e408361337d565b9250828203905081811115613e5857613e57613a09565b5b92915050565b7f546f6b656e2063617365732064697361626c6564206e6f770000000000000000600082015250565b6000613e94601883613439565b9150613e9f82613e5e565b602082019050919050565b60006020820190508181036000830152613ec381613e87565b9050919050565b6000613ed58261337d565b9150613ee08361337d565b9250828201905080821115613ef857613ef7613a09565b5b92915050565b6000613f098261337d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613f3b57613f3a613a09565b5b600182019050919050565b60006dffffffffffffffffffffffffffff82169050919050565b613f6981613f46565b8114613f7457600080fd5b50565b600081519050613f8681613f60565b92915050565b600063ffffffff82169050919050565b613fa581613f8c565b8114613fb057600080fd5b50565b600081519050613fc281613f9c565b92915050565b600080600060608486031215613fe157613fe0613378565b5b6000613fef86828701613f77565b935050602061400086828701613f77565b925050604061401186828701613fb3565b9150509250925092565b7f4e6f207265736572766500000000000000000000000000000000000000000000600082015250565b6000614051600a83613439565b915061405c8261401b565b602082019050919050565b6000602082019050818103600083015261408081614044565b9050919050565b60008151905061409681613512565b92915050565b6000602082840312156140b2576140b1613378565b5b60006140c084828501614087565b91505092915050565b7f496e76616c696420707269636500000000000000000000000000000000000000600082015250565b60006140ff600d83613439565b915061410a826140c9565b602082019050919050565b6000602082019050818103600083015261412e816140f2565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61419981613500565b82525050565b60006141ab8383614190565b60208301905092915050565b6000602082019050919050565b60006141cf82614164565b6141d9818561416f565b93506141e483614180565b8060005b838110156142155781516141fc888261419f565b9750614207836141b7565b9250506001810190506141e8565b5085935050505092915050565b60006080820190506142376000830187613b10565b818103602083015261424981866141c4565b90506142586040830185613797565b61426560608301846135e1565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000819050919050565b6000819050919050565b6142c26142bd8261429d565b6142a7565b82525050565b6000819050919050565b6142e36142de8261337d565b6142c8565b82525050565b60008160601b9050919050565b6000614301826142e9565b9050919050565b6000614313826142f6565b9050919050565b61432b61432682613500565b614308565b82525050565b600061433d82866142b1565b60208201915061434d82856142d2565b60208201915061435d828461431a565b601482019150819050949350505050565b60006143798261337d565b91506143848361337d565b92508261439457614393613a7a565b5b828206905092915050565b60006060820190506143b46000830186613797565b6143c160208301856135e1565b6143ce60408301846135e1565b949350505050565b7f4d6178696d756d20746f6b656e207065722077616c6c65742072656163686564600082015250565b600061440c602083613439565b9150614417826143d6565b602082019050919050565b6000602082019050818103600083015261443b816143ff565b9050919050565b600061445d614458614453846134e0565b613ae4565b6134e0565b9050919050565b600061446f82614442565b9050919050565b600061448182614464565b9050919050565b61449181614476565b82525050565b600060a0820190506144ac60008301886135e1565b6144b96020830187613b10565b81810360408301526144cb81866141c4565b90506144da6060830185614488565b6144e760808301846135e1565b969550505050505056fea2646970667358221220b49cfa279018054d00c5bd4ce0f943faab20ecf256a784bc4b5274208e73c54e64736f6c63430008140033000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Deployed Bytecode
0x6080604052600436106102765760003560e01c80637ab18aad1161014f578063bca93cf5116100c1578063df5fef921161007a578063df5fef9214610984578063ead267e7146109ad578063f18e7951146109d8578063f2fde38b14610a01578063f69e204614610a2a578063f906b61814610a415761027d565b8063bca93cf514610850578063c40d24b21461087b578063c92f69a9146108b8578063cc66ccea146108e1578063d58a90a71461091e578063dd62ed3e146109475761027d565b80639592d424116101135780639592d4241461072a57806395d89b4114610755578063a8aa1b3114610780578063a9059cbb146107ab578063aa3164c4146107e8578063b865e5d9146108255761027d565b80637ab18aad1461061c5780637d6731701461065a578063846f299e146106855780638da5cb5b146106c2578063946da64e146106ed5761027d565b8063328881df116101e85780635055c413116101ac5780635055c4131461051c5780636182d05d1461054757806365cf7c9b1461057257806367c7f5951461059d57806370a08231146105c8578063715018a6146106055761027d565b8063328881df1461045d5780633688555614610486578063372500ab146104af5780633c6ece75146104c6578063489f91d6146104f15761027d565b806317ed9d9d1161023a57806317ed9d9d1461033957806318160ddd146103645780631ae483b61461038f5780632073b17c146103b857806323b872dd146103f5578063313ce567146104325761027d565b806301339c211461028257806302f729b81461028c57806306fdde03146102b5578063095ea7b3146102e05780630c7c5c2a1461031d5761027d565b3661027d57005b600080fd5b61028a610a6c565b005b34801561029857600080fd5b506102b360048036038101906102ae91906133b3565b610c1a565b005b3480156102c157600080fd5b506102ca610c7a565b6040516102d791906134be565b60405180910390f35b3480156102ec57600080fd5b506103076004803603810190610302919061353e565b610d0c565b6040516103149190613599565b60405180910390f35b610337600480360381019061033291906135b4565b610d2f565b005b34801561034557600080fd5b5061034e610f11565b60405161035b91906135f0565b60405180910390f35b34801561037057600080fd5b50610379610f1e565b60405161038691906135f0565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b19190613637565b610f28565b005b3480156103c457600080fd5b506103df60048036038101906103da91906135b4565b611075565b6040516103ec91906135f0565b60405180910390f35b34801561040157600080fd5b5061041c60048036038101906104179190613664565b6111db565b6040516104299190613599565b60405180910390f35b34801561043e57600080fd5b5061044761120a565b60405161045491906136d3565b60405180910390f35b34801561046957600080fd5b50610484600480360381019061047f91906136ee565b611213565b005b34801561049257600080fd5b506104ad60048036038101906104a891906135b4565b61122b565b005b3480156104bb57600080fd5b506104c461130b565b005b3480156104d257600080fd5b506104db611326565b6040516104e891906135f0565b60405180910390f35b3480156104fd57600080fd5b5061050661132c565b60405161051391906135f0565b60405180910390f35b34801561052857600080fd5b50610531611332565b60405161053e9190613599565b60405180910390f35b34801561055357600080fd5b5061055c611345565b60405161056991906135f0565b60405180910390f35b34801561057e57600080fd5b5061058761150a565b60405161059491906135f0565b60405180910390f35b3480156105a957600080fd5b506105b2611510565b6040516105bf91906135f0565b60405180910390f35b3480156105d457600080fd5b506105ef60048036038101906105ea9190613741565b611516565b6040516105fc91906135f0565b60405180910390f35b34801561061157600080fd5b5061061a61155e565b005b34801561062857600080fd5b50610643600480360381019061063e9190613741565b611572565b60405161065192919061376e565b60405180910390f35b34801561066657600080fd5b5061066f611596565b60405161067c91906135f0565b60405180910390f35b34801561069157600080fd5b506106ac60048036038101906106a791906135b4565b61159c565b6040516106b991906135f0565b60405180910390f35b3480156106ce57600080fd5b506106d761186d565b6040516106e491906137a6565b60405180910390f35b3480156106f957600080fd5b50610714600480360381019061070f9190613741565b611897565b604051610721919061387f565b60405180910390f35b34801561073657600080fd5b5061073f611931565b60405161074c91906135f0565b60405180910390f35b34801561076157600080fd5b5061076a611937565b60405161077791906134be565b60405180910390f35b34801561078c57600080fd5b506107956119c9565b6040516107a291906137a6565b60405180910390f35b3480156107b757600080fd5b506107d260048036038101906107cd919061353e565b6119ed565b6040516107df9190613599565b60405180910390f35b3480156107f457600080fd5b5061080f600480360381019061080a91906135b4565b611a10565b60405161081c91906135f0565b60405180910390f35b34801561083157600080fd5b5061083a611a28565b60405161084791906135f0565b60405180910390f35b34801561085c57600080fd5b50610865611a2e565b60405161087291906138c2565b60405180910390f35b34801561088757600080fd5b506108a2600480360381019061089d9190613741565b611a54565b6040516108af9190613599565b60405180910390f35b3480156108c457600080fd5b506108df60048036038101906108da91906138dd565b611a74565b005b3480156108ed57600080fd5b5061090860048036038101906109039190613741565b611ad7565b60405161091591906135f0565b60405180910390f35b34801561092a57600080fd5b506109456004803603810190610940919061391d565b611bcf565b005b34801561095357600080fd5b5061096e6004803603810190610969919061395d565b611c0f565b60405161097b91906135f0565b60405180910390f35b34801561099057600080fd5b506109ab60048036038101906109a6919061391d565b611c96565b005b3480156109b957600080fd5b506109c2611ce2565b6040516109cf91906135f0565b60405180910390f35b3480156109e457600080fd5b506109ff60048036038101906109fa9190613741565b611ce8565b005b348015610a0d57600080fd5b50610a286004803603810190610a239190613741565b611d86565b005b348015610a3657600080fd5b50610a3f611e0c565b005b348015610a4d57600080fd5b50610a56611ea9565b604051610a639190613599565b60405180910390f35b610a74611ebc565b6001600760026101000a81548160ff021916908315150217905550600760039054906101000a900460ff1615610adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad6906139e9565b60405180910390fd5b6001600760036101000a81548160ff02191690831515021790555042600881905550600060646055610b1030611516565b610b1a9190613a38565b610b249190613aa9565b9050610b51307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d83611f43565b7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff1663f305d71947308460008033426040518863ffffffff1660e01b8152600401610bb696959493929190613b1f565b60606040518083038185885af1158015610bd4573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610bf99190613b95565b505050506000600760026101000a81548160ff021916908315150217905550565b610c22611ebc565b620493e0851115610c3257600080fd5b84600b81905550601e841115610c4757600080fd5b83600d81905550620493e0831115610c5e57600080fd5b82600c8190555081600e8190555080600f819055505050505050565b606060038054610c8990613c17565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb590613c17565b8015610d025780601f10610cd757610100808354040283529160200191610d02565b820191906000526020600020905b815481529060010190602001808311610ce557829003601f168201915b5050505050905090565b600080610d17611f55565b9050610d24818585611f43565b600191505092915050565b610d37611f5d565b600760019054906101000a900460ff16610d86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7d90613c94565b60405180910390fd5b6000610d918261159c565b905080341015610dd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcd90613d00565b60405180910390fd5b60006064600f34610de79190613a38565b610df19190613aa9565b90506000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682604051610e3b90613d51565b60006040518083038185875af1925050503d8060008114610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b5050905080610e8b57600080fd5b600760049054906101000a900460ff1615610ea957610ea8611fa3565b5b610eb2846121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c7716856000604051610efb929190613d66565b60405180910390a2505050610f0e61227b565b50565b6802b5e3af16b188000081565b6000600254905090565b610f30611ebc565b6001600760026101000a81548160ff021916908315150217905550600760049054906101000a900460ff161580610f745750600760059054906101000a900460ff16155b610f7d57600080fd5b8015611021576000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1647604051610fcb90613d51565b60006040518083038185875af1925050503d8060008114611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b505090508061101b57600080fd5b50611057565b611055601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661105030611516565b6119ed565b505b6000600760026101000a81548160ff02191690831515021790555050565b600061107f611f5d565b6000601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020183815481106110d5576110d4613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905043811061113c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113390613e0a565b60405180910390fd5b6111463385612285565b610100436111549190613e2a565b81111561116d57611166818333612403565b9250611172565b600192505b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc846040516111b891906135f0565b60405180910390a26111cc33846001612480565b50506111d661227b565b919050565b6000806111e6611f55565b90506111f3858285612507565b6111fe85858561259b565b60019150509392505050565b60006012905090565b61121b611ebc565b611226838383612480565b505050565b611233611f5d565b600760009054906101000a900460ff16611282576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127990613eaa565b60405180910390fd5b6000816802b5e3af16b18800006112999190613a38565b90506112a5338261268f565b6112ae826121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c77168360016040516112f7929190613d66565b60405180910390a25061130861227b565b50565b611313611f5d565b61131c33612711565b61132461227b565b565b600f5481565b60095481565b600760019054906101000a900460ff1681565b600061134f611f5d565b60004390506000610100436113649190613e2a565b9050600033905060005b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180549050811015611497576000601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061141157611410613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905085811015611481578481111561146357611451818386612403565b8761145c9190613eca565b9650611472565b868061146e90613efe565b9750505b61147c8484612285565b611490565b828061148c90613efe565b9350505b505061136e565b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc866040516114dd91906135f0565b60405180910390a260008511156114fb576114fa33866001612480565b5b5050505061150761227b565b90565b60085481565b600c5481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611566611ebc565b61157060006127be565b565b60116020528060005260406000206000915090508060000154908060010154905082565b600e5481565b600080600c54620f42406115b09190613e2a565b90506000807f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190613fc8565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156116795750600081115b6116b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116af90614067565b60405180910390fd5b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177e919061409c565b73ffffffffffffffffffffffffffffffffffffffff16146117a457808280925081935050505b600081670de0b6b3a7640000846117bb9190613a38565b6117c59190613aa9565b90506000810361180a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180190614115565b60405180910390fd5b6000670de0b6b3a7640000826802b5e3af16b188000061182a9190613a38565b6118349190613aa9565b90506000620f424086836118489190613a38565b6118529190613aa9565b905087816118609190613a38565b9650505050505050919050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180548060200260200160405190810160405280929190818152602001828054801561192557602002820191906000526020600020905b815481526020019060010190808311611911575b50505050509050919050565b600a5481565b60606004805461194690613c17565b80601f016020809104026020016040519081016040528092919081815260200182805461197290613c17565b80156119bf5780601f10611994576101008083540402835291602001916119bf565b820191906000526020600020905b8154815290600101906020018083116119a257829003601f168201915b5050505050905090565b7f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544181565b6000806119f8611f55565b9050611a0581858561259b565b600191505092915050565b60126020528060005260406000206000915090505481565b600d5481565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60136020528060005260406000206000915054906101000a900460ff1681565b611a7c611ebc565b80601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600080601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015490506000826802b5e3af16b1880000611b7d9190613a38565b9050600062015180600b548442611b949190613e2a565b611b9e9190613a38565b611ba89190613aa9565b9050620f42408183611bba9190613a38565b611bc49190613aa9565b945050505050919050565b611bd7611ebc565b81600760046101000a81548160ff02191690831515021790555080600760056101000a81548160ff0219169083151502179055505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611c9e611ebc565b8115611cc35780600760006101000a81548160ff021916908315150217905550611cde565b80600760016101000a81548160ff0219169083151502179055505b5050565b600b5481565b3373ffffffffffffffffffffffffffffffffffffffff16601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d4257600080fd5b80601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611d8e611ebc565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e005760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611df791906137a6565b60405180910390fd5b611e09816127be565b50565b611e14611f5d565b6000611e1f33611ad7565b905060006802b5e3af16b188000082611e389190613aa9565b905060008103611e49575050611e9f565b42601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550611e9c33826000612480565b50505b611ea761227b565b565b600760009054906101000a900460ff1681565b611ec4611f55565b73ffffffffffffffffffffffffffffffffffffffff16611ee261186d565b73ffffffffffffffffffffffffffffffffffffffff1614611f4157611f05611f55565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611f3891906137a6565b60405180910390fd5b565b611f508383836001612884565b505050565b600033905090565b600260065403611f99576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600681905550565b6001600760026101000a81548160ff021916908315150217905550600f54471061218c576000600267ffffffffffffffff811115611fe457611fe3614135565b5b6040519080825280602002602001820160405280156120125781602001602082028036833780820191505090505b5090507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160008151811061204a57612049613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050308160018151811061209957612098613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff1663b6f9de954760008461dead6001426121239190613eca565b6040518663ffffffff1660e01b81526004016121429493929190614222565b6000604051808303818588803b15801561215b57600080fd5b505af115801561216f573d6000803e3d6000fd5b505050505061218a61dead61218561dead611516565b61268f565b505b6000600760026101000a81548160ff021916908315150217905550565b6000600d54436121b99190613eca565b905060005b8281101561227657601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201600954908060018154018082558091505060019003906000526020600020016000909190919091505581601260006009548152602001908152602001600020819055506009600081548092919061225e90613efe565b9190505550808061226e90613efe565b9150506121be565b505050565b6001600681905550565b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002016001601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201805490506123199190613e2a565b8154811061232a57612329613d8f565b5b9060005260206000200154601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061238957612388613d8f565b5b9060005260206000200181905550601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018054806123e9576123e861426e565b5b600190038181906000526020600020016000905590555050565b600080600160648640868660405160200161242093929190614331565b6040516020818303038152906040528051906020012060001c612443919061436e565b61244d9190613eca565b905060058111612461576003915050612479565b60148111612473576002915050612479565b60019150505b9392505050565b80156124905761248f83612711565b5b81600a60008282546124a29190613eca565b9250508190555081601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546124fb9190613eca565b92505081905550505050565b60006125138484611c0f565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146125955781811015612585578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161257c9392919061439f565b60405180910390fd5b61259484848484036000612884565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361260d5760006040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260040161260491906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361267f5760006040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161267691906137a6565b60405180910390fd5b61268a838383612a5b565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036127015760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016126f891906137a6565b60405180910390fd5b61270d82600083612a5b565b5050565b600061271c82611ad7565b90506000620f424061c350836127329190613a38565b61273c9190613aa9565b9050600082146127725761275b8382846127569190613e2a565b612de6565b6127713060028361276c9190613aa9565b612de6565b5b42601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036128f65760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016128ed91906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129685760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161295f91906137a6565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612a55578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a4c91906135f0565b60405180910390a35b50505050565b601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680612afc5750601360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b80612b135750600760029054906101000a900460ff165b15612b2857612b23838383612e68565b612de1565b60007f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612bcf57507f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b9050600081612bdf576000612c01565b620f4240612beb61308d565b84612bf69190613a38565b612c009190613aa9565b5b90506000811115612c1857612c17853083612e68565b5b8083612c249190613e2a565b9250612c2e6130d5565b8015612c8657507f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b8015612cde57507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15612d5c5760646005695e0549c9632e1d800000612cfc9190613a38565b612d069190613aa9565b83612d1086611516565b612d1a9190613eca565b1115612d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d5290614422565b60405180910390fd5b5b600760059054906101000a900460ff168015612dc457507f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15612dd357612dd2836130ee565b5b612dde858585612e68565b50505b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e585760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612e4f91906137a6565b60405180910390fd5b612e6460008383612a5b565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612eba578060026000828254612eae9190613eca565b92505081905550612f8d565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612f46578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612f3d9392919061439f565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612fd65780600260008282540392505081905550613023565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161308091906135f0565b60405180910390a3505050565b6000806008544261309e9190613e2a565b90506101688111156130b5576175309150506130d2565b60b48111156130ca57620186a09150506130d2565b6202bf209150505b90565b60006078600854426130e79190613e2a565b1115905090565b6001600760026101000a81548160ff021916908315150217905550600061311d8261311830611516565b61335f565b9050600e5481101561312f5750613341565b6000600267ffffffffffffffff81111561314c5761314b614135565b5b60405190808252806020026020018201604052801561317a5781602001602082028036833780820191505090505b509050308160008151811061319257613191613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160018151811061320157613200613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050613288307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000612884565b7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff1663791ac94783600084601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16426040518663ffffffff1660e01b815260040161330c959493929190614497565b600060405180830381600087803b15801561332657600080fd5b505af115801561333a573d6000803e3d6000fd5b5050505050505b6000600760026101000a81548160ff02191690831515021790555050565b600081831061336e5781613370565b825b905092915050565b600080fd5b6000819050919050565b6133908161337d565b811461339b57600080fd5b50565b6000813590506133ad81613387565b92915050565b600080600080600060a086880312156133cf576133ce613378565b5b60006133dd8882890161339e565b95505060206133ee8882890161339e565b94505060406133ff8882890161339e565b93505060606134108882890161339e565b92505060806134218882890161339e565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346857808201518184015260208101905061344d565b60008484015250505050565b6000601f19601f8301169050919050565b60006134908261342e565b61349a8185613439565b93506134aa81856020860161344a565b6134b381613474565b840191505092915050565b600060208201905081810360008301526134d88184613485565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061350b826134e0565b9050919050565b61351b81613500565b811461352657600080fd5b50565b60008135905061353881613512565b92915050565b6000806040838503121561355557613554613378565b5b600061356385828601613529565b92505060206135748582860161339e565b9150509250929050565b60008115159050919050565b6135938161357e565b82525050565b60006020820190506135ae600083018461358a565b92915050565b6000602082840312156135ca576135c9613378565b5b60006135d88482850161339e565b91505092915050565b6135ea8161337d565b82525050565b600060208201905061360560008301846135e1565b92915050565b6136148161357e565b811461361f57600080fd5b50565b6000813590506136318161360b565b92915050565b60006020828403121561364d5761364c613378565b5b600061365b84828501613622565b91505092915050565b60008060006060848603121561367d5761367c613378565b5b600061368b86828701613529565b935050602061369c86828701613529565b92505060406136ad8682870161339e565b9150509250925092565b600060ff82169050919050565b6136cd816136b7565b82525050565b60006020820190506136e860008301846136c4565b92915050565b60008060006060848603121561370757613706613378565b5b600061371586828701613529565b93505060206137268682870161339e565b925050604061373786828701613622565b9150509250925092565b60006020828403121561375757613756613378565b5b600061376584828501613529565b91505092915050565b600060408201905061378360008301856135e1565b61379060208301846135e1565b9392505050565b6137a081613500565b82525050565b60006020820190506137bb6000830184613797565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137f68161337d565b82525050565b600061380883836137ed565b60208301905092915050565b6000602082019050919050565b600061382c826137c1565b61383681856137cc565b9350613841836137dd565b8060005b8381101561387257815161385988826137fc565b975061386483613814565b925050600181019050613845565b5085935050505092915050565b600060208201905081810360008301526138998184613821565b905092915050565b60006138ac826134e0565b9050919050565b6138bc816138a1565b82525050565b60006020820190506138d760008301846138b3565b92915050565b600080604083850312156138f4576138f3613378565b5b600061390285828601613529565b925050602061391385828601613622565b9150509250929050565b6000806040838503121561393457613933613378565b5b600061394285828601613622565b925050602061395385828601613622565b9150509250929050565b6000806040838503121561397457613973613378565b5b600061398285828601613529565b925050602061399385828601613529565b9150509250929050565b7f546f6b656e206c61756e63686564000000000000000000000000000000000000600082015250565b60006139d3600e83613439565b91506139de8261399d565b602082019050919050565b60006020820190508181036000830152613a02816139c6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a438261337d565b9150613a4e8361337d565b9250828202613a5c8161337d565b91508282048414831517613a7357613a72613a09565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613ab48261337d565b9150613abf8361337d565b925082613acf57613ace613a7a565b5b828204905092915050565b6000819050919050565b6000819050919050565b6000613b09613b04613aff84613ada565b613ae4565b61337d565b9050919050565b613b1981613aee565b82525050565b600060c082019050613b346000830189613797565b613b4160208301886135e1565b613b4e6040830187613b10565b613b5b6060830186613b10565b613b686080830185613797565b613b7560a08301846135e1565b979650505050505050565b600081519050613b8f81613387565b92915050565b600080600060608486031215613bae57613bad613378565b5b6000613bbc86828701613b80565b9350506020613bcd86828701613b80565b9250506040613bde86828701613b80565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c2f57607f821691505b602082108103613c4257613c41613be8565b5b50919050565b7f4554482063617365732064697361626c6564206e6f7700000000000000000000600082015250565b6000613c7e601683613439565b9150613c8982613c48565b602082019050919050565b60006020820190508181036000830152613cad81613c71565b9050919050565b7f4e6f7420656e6f7567682065746820746f207061790000000000000000000000600082015250565b6000613cea601583613439565b9150613cf582613cb4565b602082019050919050565b60006020820190508181036000830152613d1981613cdd565b9050919050565b600081905092915050565b50565b6000613d3b600083613d20565b9150613d4682613d2b565b600082019050919050565b6000613d5c82613d2e565b9150819050919050565b6000604082019050613d7b60008301856135e1565b613d88602083018461358a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e6f7420636c61696d61626c6520796574000000000000000000000000000000600082015250565b6000613df4601183613439565b9150613dff82613dbe565b602082019050919050565b60006020820190508181036000830152613e2381613de7565b9050919050565b6000613e358261337d565b9150613e408361337d565b9250828203905081811115613e5857613e57613a09565b5b92915050565b7f546f6b656e2063617365732064697361626c6564206e6f770000000000000000600082015250565b6000613e94601883613439565b9150613e9f82613e5e565b602082019050919050565b60006020820190508181036000830152613ec381613e87565b9050919050565b6000613ed58261337d565b9150613ee08361337d565b9250828201905080821115613ef857613ef7613a09565b5b92915050565b6000613f098261337d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613f3b57613f3a613a09565b5b600182019050919050565b60006dffffffffffffffffffffffffffff82169050919050565b613f6981613f46565b8114613f7457600080fd5b50565b600081519050613f8681613f60565b92915050565b600063ffffffff82169050919050565b613fa581613f8c565b8114613fb057600080fd5b50565b600081519050613fc281613f9c565b92915050565b600080600060608486031215613fe157613fe0613378565b5b6000613fef86828701613f77565b935050602061400086828701613f77565b925050604061401186828701613fb3565b9150509250925092565b7f4e6f207265736572766500000000000000000000000000000000000000000000600082015250565b6000614051600a83613439565b915061405c8261401b565b602082019050919050565b6000602082019050818103600083015261408081614044565b9050919050565b60008151905061409681613512565b92915050565b6000602082840312156140b2576140b1613378565b5b60006140c084828501614087565b91505092915050565b7f496e76616c696420707269636500000000000000000000000000000000000000600082015250565b60006140ff600d83613439565b915061410a826140c9565b602082019050919050565b6000602082019050818103600083015261412e816140f2565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61419981613500565b82525050565b60006141ab8383614190565b60208301905092915050565b6000602082019050919050565b60006141cf82614164565b6141d9818561416f565b93506141e483614180565b8060005b838110156142155781516141fc888261419f565b9750614207836141b7565b9250506001810190506141e8565b5085935050505092915050565b60006080820190506142376000830187613b10565b818103602083015261424981866141c4565b90506142586040830185613797565b61426560608301846135e1565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000819050919050565b6000819050919050565b6142c26142bd8261429d565b6142a7565b82525050565b6000819050919050565b6142e36142de8261337d565b6142c8565b82525050565b60008160601b9050919050565b6000614301826142e9565b9050919050565b6000614313826142f6565b9050919050565b61432b61432682613500565b614308565b82525050565b600061433d82866142b1565b60208201915061434d82856142d2565b60208201915061435d828461431a565b601482019150819050949350505050565b60006143798261337d565b91506143848361337d565b92508261439457614393613a7a565b5b828206905092915050565b60006060820190506143b46000830186613797565b6143c160208301856135e1565b6143ce60408301846135e1565b949350505050565b7f4d6178696d756d20746f6b656e207065722077616c6c65742072656163686564600082015250565b600061440c602083613439565b9150614417826143d6565b602082019050919050565b6000602082019050818103600083015261443b816143ff565b9050919050565b600061445d614458614453846134e0565b613ae4565b6134e0565b9050919050565b600061446f82614442565b9050919050565b600061448182614464565b9050919050565b61449181614476565b82525050565b600060a0820190506144ac60008301886135e1565b6144b96020830187613b10565b81810360408301526144cb81866141c4565b90506144da6060830185614488565b6144e760808301846135e1565b969550505050505056fea2646970667358221220b49cfa279018054d00c5bd4ce0f943faab20ecf256a784bc4b5274208e73c54e64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
-----Decoded View---------------
Arg [0] : _WETH (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [1] : _ROUTER (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.