Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Pulseium
- Optimization enabled
- true
- Compiler version
- v0.8.20+commit.a1b79de6
- Optimization runs
- 200
- EVM Version
- shanghai
- Verified at
- 2025-07-23T23:27:18.372073Z
Contract source code
// SPDX-License-Identifier: MIT
// File: Pulseium/Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: Pulseium/Ownable.sol
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @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 {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_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);
}
}
// File: Pulseium/IERC20.sol
pragma solidity ^0.8.0;
/**
* @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 amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
// File: Pulseium/IERC20Metadata.sol
pragma solidity ^0.8.0;
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
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);
}
// File: Pulseium/ERC20.sol
pragma solidity ^0.8.0;
/**
* @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}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* 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.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* 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 override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override 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 value {ERC20} uses, unless this function is
* 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 override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override 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 `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` 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 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
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 `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `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.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` 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.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
// File: Pulseium/Distributor.sol
pragma solidity ^0.8.0;
/**
* @title IDistributor
* @notice Interface for the Dividend Distributor contract.
*/
interface IDistributor {
/**
* @notice Sets distribution criteria such as minimum period and minimum distribution.
* @param minPeriod Minimum time between claims for a shareholder (in seconds).
* @param minDistribution Minimum amount of reward (in wei) to trigger a distribution.
*/
function setDistributionCriteria(uint256 minPeriod, uint256 minDistribution) external;
/**
* @notice Sets the share of a specific shareholder.
* @param shareholder Address of the shareholder.
* @param amount Number of tokens held by the shareholder.
*/
function setShare(address shareholder, uint256 amount) external;
/**
* @notice Deposit native tokens (e.g., PLS or ETH) into the distributor to be shared.
*/
function deposit() external payable;
/**
* @notice Distributes rewards to shareholders using the specified gas limit.
* @param gas Maximum gas to use for distribution loop.
*/
function process(uint256 gas) external;
}
/**
* @title ReentrancyGuard
* @notice Protects against reentrant calls to functions using a simple status lock.
*/
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
*/
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
/**
* @title Distributor
* @notice Manages dividend distribution to token holders proportionally to their share.
* @dev Only callable by the token contract (owner). Uses ReentrancyGuard to prevent claim loops.
*/
contract Distributor is IDistributor, ReentrancyGuard {
/// @notice Address of the token contract that owns this distributor.
address owner;
/**
* @notice Stores shareholder-specific information for dividend tracking.
* @param amount Number of shares (tokens) the shareholder holds.
* @param totalExcluded Cumulative dividends excluded from this shareholder (to avoid double-counting).
* @param totalRealised Total amount of dividends the shareholder has received.
*/
struct Share {
uint256 amount;
uint256 totalExcluded;
uint256 totalRealised;
}
/// @notice List of all current shareholders.
address[] shareholders;
/// @notice Mapping from shareholder address to their index in the `shareholders` array.
mapping (address => uint256) public shareholderIndexes;
/// @notice Timestamp of the last claim for each shareholder.
mapping (address => uint256) public shareholderClaims;
/// @notice Mapping from address to their share details.
mapping (address => Share) public shares;
/// @notice Emitted when the distribution criteria are updated.
/// @param minPeriod Minimum time between distributions (in seconds).
/// @param minDistribution Minimum amount of dividends to trigger a distribution (in wei).
event DistributionCriteriaUpdate(uint256 minPeriod, uint256 minDistribution);
/// @notice Emitted when new funds are deposited into the distributor.
/// @param amount Amount of native tokens (e.g., PLS or ETH) deposited.
event NewFundDeposit(address indexed depositor, uint256 amount);
/// @notice Emitted when dividends are distributed to a shareholder.
/// @param shareholder The address receiving the dividend.
/// @param amount The amount of native tokens (PLS) distributed.
event DividendDistributed(address indexed shareholder, uint256 amount);
/// @notice Total number of shares held by all shareholders.
uint256 public totalShares;
/// @notice Total amount of dividends that have been deposited.
uint256 public totalDividends;
/// @notice Total amount of dividends that have been distributed.
uint256 public totalDistributed;
/// @notice Dividends per share scaled by the `dividendsPerShareAccuracyFactor`.
uint256 public dividendsPerShare;
/// @notice Factor used to maintain precision when calculating dividends per share.
uint256 public dividendsPerShareAccuracyFactor = 10 ** 36;
/// @notice Minimum time between dividend distributions for each shareholder (in seconds).
uint256 public minPeriod = 10;
/// @notice Minimum dividend amount (in wei) required to trigger a distribution.
uint256 public minDistribution = 1 * (10**10);
/// @notice Current index used to iterate through shareholders during processing.
uint256 currentIndex;
/**
* @dev Modifier to restrict access to the contract owner.
*/
modifier onlyOwner() {
require(msg.sender == owner, "!Token"); _;
}
constructor () {
owner = msg.sender;
}
/**
* @notice Accepts incoming native token transfers (PLS, ETH).
*/
receive() external payable {}
/**
* @inheritdoc IDistributor
*/
function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution) external override onlyOwner {
minPeriod = _minPeriod;
minDistribution = _minDistribution;
emit DistributionCriteriaUpdate(minPeriod, minDistribution);
}
/**
* @inheritdoc IDistributor
*/
function setShare(address shareholder, uint256 amount) external override onlyOwner {
if(shares[shareholder].amount > 0)
{
distributeDividend(shareholder);
}
if(amount > 0 && shares[shareholder].amount == 0)
{
addShareholder(shareholder);
}
else if(amount == 0 && shares[shareholder].amount > 0)
{
removeShareholder(shareholder);
}
totalShares = totalShares - shares[shareholder].amount + amount;
shares[shareholder].amount = amount;
shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount);
}
/**
* @inheritdoc IDistributor
*/
function deposit() external override onlyOwner payable {
totalDividends += msg.value;
dividendsPerShare += ((dividendsPerShareAccuracyFactor * msg.value) / totalShares);
emit NewFundDeposit(msg.sender, msg.value);
}
/**
* @inheritdoc IDistributor
*/
function process(uint256 gas) external override onlyOwner {
uint256 shareholderCount = shareholders.length;
if(shareholderCount == 0) { return; }
uint256 gasUsed = 0;
uint256 gasLeft = gasleft();
uint256 iterations = 0;
while(gasUsed < gas && iterations < shareholderCount) {
if(currentIndex >= shareholderCount)
{
currentIndex = 0;
}
if(shouldDistribute(shareholders[currentIndex]))
{
distributeDividend(shareholders[currentIndex]);
}
gasUsed = gasUsed + gasLeft - gasleft();
gasLeft = gasleft();
currentIndex++;
iterations++;
}
}
/**
* @notice Determines if a shareholder is eligible for a distribution.
* @param shareholder Address of the shareholder.
* @return Whether the shareholder should receive a distribution.
*/
function shouldDistribute(address shareholder) private view returns (bool) {
return (shareholderClaims[shareholder] + minPeriod) < block.timestamp && getUnpaidEarnings(shareholder) > minDistribution;
}
/**
* @notice Distributes available earnings to a shareholder.
* @param shareholder Address to distribute to.
*/
function distributeDividend(address shareholder) private {
if(shares[shareholder].amount == 0){ return; }
uint256 amount = getUnpaidEarnings(shareholder);
if(amount > 0)
{
(bool success, ) = shareholder.call{value: amount}("");
if(success)
{
totalDistributed += amount;
shareholderClaims[shareholder] = block.timestamp;
shares[shareholder].totalRealised = shares[shareholder].totalRealised + amount;
shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount);
emit DividendDistributed(shareholder, amount);
}
}
}
/**
* @notice Claims available dividends for the sender.
* @dev Protected by nonReentrant to avoid recursive distribution.
*/
function claimReward() external nonReentrant {
if(shouldDistribute(msg.sender))
{
distributeDividend(msg.sender);
}
}
/**
* @notice Calculates unpaid earnings for a shareholder.
* @param shareholder Address of the shareholder.
* @return The amount of unpaid earnings.
*/
function getUnpaidEarnings(address shareholder) public view returns (uint256) {
if(shares[shareholder].amount == 0){ return 0; }
uint256 shareholderTotalDividends = getCumulativeDividends(shares[shareholder].amount);
uint256 shareholderTotalExcluded = shares[shareholder].totalExcluded;
if(shareholderTotalDividends <= shareholderTotalExcluded){ return 0; }
return shareholderTotalDividends - shareholderTotalExcluded;
}
/**
* @notice Calculates the total dividends for a given amount of shares.
* @param share The number of shares.
* @return The total cumulative dividends for those shares.
*/
function getCumulativeDividends(uint256 share) private view returns (uint256) {
return share * dividendsPerShare / dividendsPerShareAccuracyFactor;
}
/**
* @notice Adds a shareholder to the list.
* @param shareholder Address to add.
*/
function addShareholder(address shareholder) private {
shareholderIndexes[shareholder] = shareholders.length;
shareholders.push(shareholder);
}
/**
* @notice Removes a shareholder from the list.
* @param shareholder Address to remove.
*/
function removeShareholder(address shareholder) private {
shareholders[shareholderIndexes[shareholder]] = shareholders[shareholders.length-1];
shareholderIndexes[shareholders[shareholders.length-1]] = shareholderIndexes[shareholder];
shareholders.pop();
}
}
// File: Pulseium/IPulseX.sol
pragma solidity 0.8.20;
/// @title PulseX Factory Interface
/// @notice Interface for creating liquidity pairs on PulseX
interface IPulseXFactory {
/// @notice Creates a new trading pair between two tokens
/// @param tokenA Address of the first token
/// @param tokenB Address of the second token
/// @return pair Address of the newly created pair contract
function createPair(address tokenA, address tokenB) external returns (address pair);
}
/// @title PulseX Router Interface
/// @notice Interface for interacting with PulseX Router for swaps and liquidity
interface IPulseXRouter {
/// @notice Returns the address of the factory contract
/// @return Address of the PulseX factory
function factory() external pure returns (address);
/// @notice Returns the address of the wrapped PLS token (WPLS)
/// @return Address of the WPLS token
function WPLS() external pure returns (address);
/**
* @notice Swaps an exact amount of input tokens for ETH
* @dev Supports fee-on-transfer tokens
* @param amountIn Amount of input tokens to send
* @param amountOutMin Minimum amount of ETH to receive
* @param path Array of token addresses for the swap path
* @param to Address to receive the ETH
* @param deadline Unix timestamp after which the transaction will revert
*/
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
/**
* @notice Adds liquidity to an ETH/token pair
* @param token Address of the ERC20 token
* @param amountTokenDesired Amount of tokens to add as liquidity
* @param amountTokenMin Minimum amount of tokens to add (slippage control)
* @param amountETHMin Minimum amount of ETH to add (slippage control)
* @param to Address to receive liquidity tokens
* @param deadline Unix timestamp after which the transaction will revert
* @return amountToken Amount of tokens added
* @return amountETH Amount of ETH added
* @return liquidity Amount of liquidity tokens received
*/
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}
/// @title PulseX Pair Interface
/// @notice Interface for querying pair token addresses in a PulseX liquidity pool
interface IPulseXPair {
/// @notice Returns the address of token0 in the pair
/// @return Address of token0
function token0() external view returns (address);
/// @notice Returns the address of token1 in the pair
/// @return Address of token1
function token1() external view returns (address);
}
// File: Pulseium/Pulseium.sol
pragma solidity 0.8.20;
/// @title Pulseium Token Contract
/// @author
/// @notice Custom ERC20 token with auto liquidity, reward distribution, and fee mechanisms on PulseChain
/// @dev Uses PulseXRouter for swaps and liquidity. Rewards distributed via custom Distributor contract.
contract Pulseium is Ownable, ERC20 {
/// @notice Fee taken for reward distribution
uint256 public immutable rewardFee;
/// @notice Fee taken for burning
uint256 public immutable burnFee;
/// @notice Fee taken for adding liquidity
uint256 public immutable liquidityFee;
/// @notice Total fee that gets swapped (liquidity + reward)
uint256 private immutable swappableFee;
/// @notice Denominator for fee calculation (e.g. 10000 for basis points)
uint256 private immutable divider;
/// @notice Denominator for share calculation (e.g. 100 for basis points)
uint256 private immutable shareDivider;
/// @notice Gas limit for reward distributor processing
uint256 public distributorGas;
/// @notice Minimum token threshold before swap and liquify
uint256 public swapThreshold;
/// @notice Flag indicating if the contract is currently performing a swap
bool private swapping;
/// @notice Whether trading is enabled
bool public tradingEnabled;
/// @notice Whether reward distribution is enabled
bool public distributionEnabled;
/// @notice List of recognized liquidity pair addressess
address[] public liquidityPairs;
/// @notice Address to which burned tokens are sent
address public immutable burnWallet;
/// @notice Main PulseX pair address
address public immutable pulsexPair;
/// @notice PulseX Router interface
IPulseXRouter public immutable pulsexRouter;
/// @notice Custom reward distributor instance
Distributor public rewardDistributor;
/// @notice Wallets excluded from fees
mapping(address => bool) public isExcludedFromFee;
/// @notice Wallets excluded from rewards
mapping(address => bool) public isExcludedFromReward;
/// @notice Mapping for identifying liquidity pair addresses
mapping(address => bool) public isLiquidityPair;
/// @notice Shares for each LP pair in the reward calculation
mapping(address => uint256) public liquidityPairShare;
/// @notice Emitted when the swap threshold is updated
event SwapThresholdUpdated(uint256 amount);
/// @notice Emitted when a liquidity pair is added or removed
event LPPairUpdated(address indexed pair, bool status);
/// @notice Emitted when a wallet is excluded or included in fees
event WalletExcludeFromFee(address indexed wallet, bool status);
/// @notice Emitted when a wallet is excluded or included in rewards
event WalletExcludedFromReward(address indexed wallet, bool value);
/// @notice Emitted when reward distribution criteria are updated
event DistributionCriteriaUpdated(uint256 minPeriod, uint256 minDistribution);
/// @notice Emitted when the gas limit for distributor is updated
event DistributorGasUpdated(uint256 distributorGas);
/// @notice Emitted when trading is enabled
event TradingEnabled();
/// @notice Emitted when adding liquidity fails
event LiquidityAddFailed(uint256 tokenAmount, uint256 plsAmount);
/// @notice Emitted when swapping tokens for PLS fails
event SwapFailed(uint256 tokenAmount);
/// @notice Emitted when reward distribution is enabled or disabled
event DistributionStatusUpdated(bool status);
/// @notice Emitted when lp share update
event LPPairShareUpdated(address indexed pair, uint256 newShare);
/// @notice Constructor to initialize token and setup fees, LP, and exclusions
constructor() ERC20("Pulseium", "PSM") {
pulsexRouter = IPulseXRouter(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
pulsexPair = IPulseXFactory(pulsexRouter.factory()).createPair(address(this), pulsexRouter.WPLS());
rewardDistributor = new Distributor();
burnWallet = address(0x0000000000000000000000000000000000000369);
distributionEnabled = true;
rewardFee = 350;
burnFee = 50;
liquidityFee = 100;
swappableFee = (rewardFee + liquidityFee);
divider = 10000;
shareDivider = 100;
distributorGas = 250000;
swapThreshold = 250_000_000 * (10**18);
isLiquidityPair[address(pulsexPair)] = true;
isExcludedFromFee[address(msg.sender)] = true;
isExcludedFromFee[address(this)] = true;
isExcludedFromFee[address(burnWallet)] = true;
isExcludedFromReward[address(this)] = true;
isExcludedFromReward[address(pulsexPair)] = true;
isExcludedFromReward[address(burnWallet)] = true;
liquidityPairs.push(pulsexPair);
_mint(address(msg.sender), 1_555_369_000_000 * (10**18));
}
/// @notice Allows the contract to receive native PLS
receive() external payable {}
/// @notice Updates the minimum token amount before swap is triggered
/// @param _amount New threshold in token units
function updateSwapThreshold(uint256 _amount) external onlyOwner {
require(_amount <= totalSupply(), "Amount cannot be over the total supply.");
require(_amount >= 1000 * (10**18), "Minimum `1000` token per swap required");
swapThreshold = _amount;
emit SwapThresholdUpdated(_amount);
}
/// @notice Excludes or includes a wallet from paying fees
/// @param _wallet Address of the wallet
/// @param _status True to exclude, false to include
function excludeWalletFromFee(address _wallet, bool _status) external onlyOwner {
require(_wallet != address(0), "Wallet address is not correct");
require(isExcludedFromFee[_wallet] != _status, "Wallet is already the value of 'status'");
isExcludedFromFee[_wallet] = _status;
emit WalletExcludeFromFee(_wallet, _status);
}
/// @notice Enables token trading
function enableTrading() external onlyOwner {
require(!tradingEnabled, "Trading already enabled");
tradingEnabled = true;
emit TradingEnabled();
}
/// @notice Excludes or includes a wallet from receiving rewards
/// @param _wallet Address of the wallet
/// @param _status True to exclude, false to include
function excludeWalletFromReward(address _wallet, bool _status) external onlyOwner {
require(_wallet != address(0), "Zero address");
require(isExcludedFromReward[_wallet] != _status, "Wallet is already the value of 'status'");
isExcludedFromReward[_wallet] = _status;
if(_status) {
try rewardDistributor.setShare(_wallet, 0) {} catch {}
} else {
_updateShares(_wallet);
}
emit WalletExcludedFromReward(_wallet, _status);
}
/// @notice Sets the reward distribution timing and minimum thresholds
/// @param _minPeriod Minimum time between distributions
/// @param _minDistribution Minimum token amount required for a distribution
function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution) external onlyOwner {
require(_minDistribution > 0, "Min. distribution can't be zero");
try rewardDistributor.setDistributionCriteria(_minPeriod, _minDistribution) {} catch {}
emit DistributionCriteriaUpdated(_minPeriod, _minDistribution);
}
/// @notice Sets the gas limit for the distributor
/// @param _gas New gas limit
function setDistributorGas(uint256 _gas) external onlyOwner {
require(_gas < 750000, "Gas is greater than limit");
distributorGas = _gas;
emit DistributorGasUpdated(_gas);
}
/// @notice Enables or disables reward distribution
/// @param status True to enable, false to disable
function setDistributionStatus(bool status) external onlyOwner {
distributionEnabled = status;
emit DistributionStatusUpdated(status);
}
/// @notice Adds or removes a liquidity pair
/// @param _pair The LP token address
/// @param _status True to add, false to remove
/// @param _share The share of the LP in reward calculations (basis points)
function setLiquidityPair(address _pair, bool _status, uint256 _share) external onlyOwner {
require(isLiquidityPair[_pair] != _status, "Pair is already set to that status");
require(_pair != address(pulsexPair), "Can't update the status of main pair");
if(_status)
{
require(isValidLiquidityPair(_pair), "Invalid liquidity pair");
require(_share > 0, "Share must be greater than zero");
liquidityPairs.push(_pair);
isLiquidityPair[_pair] = _status;
isExcludedFromReward[_pair] = _status;
liquidityPairShare[_pair] = _share;
}
else if(isLiquidityPair[_pair])
{
for (uint256 i = 0; i < liquidityPairs.length; i++) {
if (liquidityPairs[i] == _pair) {
liquidityPairs[i] = liquidityPairs[liquidityPairs.length - 1];
liquidityPairs.pop();
break;
}
}
liquidityPairShare[_pair] = 0;
isLiquidityPair[_pair] = _status;
isExcludedFromReward[_pair] = _status;
}
emit LPPairUpdated(_pair, _status);
}
/// @notice Updates the share of an existing liquidity pair
/// @param _pair The LP token address
/// @param _newShare The new share value in basis points (must be > 0)
function updateLiquidityPairShare(address _pair, uint256 _newShare) external onlyOwner {
require(isLiquidityPair[_pair], "Not a registered liquidity pair");
require(_newShare > 0, "Share must be greater than zero");
liquidityPairShare[_pair] = _newShare;
emit LPPairShareUpdated(_pair, _newShare);
}
/// @notice Checks if the address is a valid LP pair (includes this token)
/// @param _pair The LP token address
/// @return Whether the pair is valid
function isValidLiquidityPair(address _pair) private view returns (bool) {
try IPulseXPair(_pair).token0() returns (address token0) {
address token1 = IPulseXPair(_pair).token1();
return (token0 == address(this) || token1 == address(this));
} catch {
return false;
}
}
/// @dev Overridden ERC20 transfer to handle fee collection, swapping, and reward tracking
function _transfer(address _sender, address _recipient, uint256 _amount) internal override(ERC20) {
if (!tradingEnabled) {
require(_sender == owner() || _recipient == owner(), "Trading not enabled");
}
if(!swapping && isLiquidityPair[_recipient]) {
uint256 contractTokenBalance = balanceOf(address(this));
if(contractTokenBalance >= swapThreshold) {
swapping = true;
uint256 liqudityToken = (((swapThreshold * liquidityFee) / (swappableFee)) / (2));
uint256 rewardToken = ((swapThreshold * rewardFee) / (swappableFee));
uint256 swapToken = (liqudityToken + rewardToken);
swapTokensForPLS(swapToken);
uint256 PLSBalance = address(this).balance;
uint256 liqudityShare = (PLSBalance * liqudityToken) / (swapToken);
uint256 rewardShare = (PLSBalance - liqudityShare);
if(liqudityShare > 0) {
addLiquidity(liqudityToken, liqudityShare);
}
if(rewardShare > 0) {
try rewardDistributor.deposit{value: rewardShare}() {} catch {}
}
swapping = false;
}
}
if(isExcludedFromFee[_sender] || isExcludedFromFee[_recipient] || (!isLiquidityPair[_sender] && !isLiquidityPair[_recipient])) {
super._transfer(_sender, _recipient, _amount);
} else {
(uint256 _burnFee, uint256 _swappableFee) = collectFee(_amount);
if(_swappableFee > 0) {
super._transfer(_sender, address(this), _swappableFee);
}
if(_burnFee > 0) {
super._transfer(_sender, address(burnWallet), _burnFee);
}
super._transfer(_sender, _recipient, (_amount - (_swappableFee + _burnFee)));
}
if(!isExcludedFromReward[_sender]){ _updateShares(_sender); }
if(!isExcludedFromReward[_recipient]){ _updateShares(_recipient); }
if(distributionEnabled){
try rewardDistributor.process(distributorGas) {} catch {}
}
}
/// @notice Updates reward shares for a holder
/// @param _holder Address of the token or LP holder
function _updateShares(address _holder) private {
if (isExcludedFromReward[_holder]) return;
uint256 totalBalance = balanceOf(_holder);
for (uint256 i = 0; i < liquidityPairs.length; i++) {
address pair = liquidityPairs[i];
totalBalance += (((IERC20(pair).balanceOf(_holder) * liquidityPairShare[pair])) / (shareDivider));
}
try rewardDistributor.setShare(_holder, totalBalance) {} catch {}
}
/// @notice Calculates burn and other fee from the amount
/// @param _amount Token amount
/// @return burn fee and other fees in tokens
function collectFee(uint256 _amount) private view returns (uint256, uint256) {
uint256 _rewardFee = (_amount * rewardFee) / (divider);
uint256 _liquidityFee = (_amount * liquidityFee) / (divider);
uint256 _burnFee = (_amount * burnFee) / (divider);
return (_burnFee, (_rewardFee + _liquidityFee));
}
/// @notice Swaps tokens to PLS via PulseX
/// @param _tokenAmount Amount of tokens to swap
function swapTokensForPLS(uint256 _tokenAmount) private {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = pulsexRouter.WPLS();
_approve(address(this), address(pulsexRouter), _tokenAmount);
try pulsexRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
_tokenAmount,
0,
path,
address(this),
block.timestamp
){} catch {
emit SwapFailed(_tokenAmount);
}
}
/// @notice Adds liquidity to PulseX
/// @param _tokenAmount Amount of tokens to add
/// @param _PLSAmount Amount of PLS to pair with tokens
function addLiquidity(uint256 _tokenAmount, uint256 _PLSAmount) private {
_approve(address(this), address(pulsexRouter), _tokenAmount);
try pulsexRouter.addLiquidityETH{value: _PLSAmount}(
address(this),
_tokenAmount,
0,
0,
address(this),
block.timestamp
){} catch {
emit LiquidityAddFailed(_tokenAmount, _PLSAmount);
}
}
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"DistributionCriteriaUpdated","inputs":[{"type":"uint256","name":"minPeriod","internalType":"uint256","indexed":false},{"type":"uint256","name":"minDistribution","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"DistributionStatusUpdated","inputs":[{"type":"bool","name":"status","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"DistributorGasUpdated","inputs":[{"type":"uint256","name":"distributorGas","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LPPairShareUpdated","inputs":[{"type":"address","name":"pair","internalType":"address","indexed":true},{"type":"uint256","name":"newShare","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LPPairUpdated","inputs":[{"type":"address","name":"pair","internalType":"address","indexed":true},{"type":"bool","name":"status","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"LiquidityAddFailed","inputs":[{"type":"uint256","name":"tokenAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"plsAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SwapFailed","inputs":[{"type":"uint256","name":"tokenAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SwapThresholdUpdated","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TradingEnabled","inputs":[],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"WalletExcludeFromFee","inputs":[{"type":"address","name":"wallet","internalType":"address","indexed":true},{"type":"bool","name":"status","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"WalletExcludedFromReward","inputs":[{"type":"address","name":"wallet","internalType":"address","indexed":true},{"type":"bool","name":"value","internalType":"bool","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"burnFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"burnWallet","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"distributionEnabled","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"distributorGas","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enableTrading","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeWalletFromFee","inputs":[{"type":"address","name":"_wallet","internalType":"address"},{"type":"bool","name":"_status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeWalletFromReward","inputs":[{"type":"address","name":"_wallet","internalType":"address"},{"type":"bool","name":"_status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromFee","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromReward","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isLiquidityPair","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"liquidityFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"liquidityPairShare","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"liquidityPairs","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pulsexPair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IPulseXRouter"}],"name":"pulsexRouter","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract Distributor"}],"name":"rewardDistributor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDistributionCriteria","inputs":[{"type":"uint256","name":"_minPeriod","internalType":"uint256"},{"type":"uint256","name":"_minDistribution","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDistributionStatus","inputs":[{"type":"bool","name":"status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDistributorGas","inputs":[{"type":"uint256","name":"_gas","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLiquidityPair","inputs":[{"type":"address","name":"_pair","internalType":"address"},{"type":"bool","name":"_status","internalType":"bool"},{"type":"uint256","name":"_share","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"swapThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"tradingEnabled","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateLiquidityPairShare","inputs":[{"type":"address","name":"_pair","internalType":"address"},{"type":"uint256","name":"_newShare","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateSwapThreshold","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x6101a060405234801562000011575f80fd5b506040518060400160405280600881526020016750756c736569756d60c01b8152506040518060400160405280600381526020016250534d60e81b81525062000069620000636200039660201b60201c565b6200039a565b600462000077838262000580565b50600562000086828262000580565b505073165c3410fc91ef562c50559f7d2289febed552d96101808190526040805163c45a015560e01b8152905191925063c45a01559160048083019260209291908290030181865afa158015620000df573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000105919062000648565b6001600160a01b031663c9c6539630610180516001600160a01b031663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000154573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200017a919062000648565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303815f875af1158015620001c5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001eb919062000648565b6001600160a01b0316610160526040516200020690620004d3565b604051809103905ff08015801562000220573d5f803e3d5ffd5b50600a80546001600160a01b03929092166001600160a01b0319909216919091179055610369610140526008805462ff000019166201000017905561015e6080819052603260a052606460c08190526200027a9162000677565b60e052612710610100526064610120526203d0906006556acecb8f27f4200f3a000000600755610160516001600160a01b039081165f818152600d602090815260408083208054600160ff19918216811790925533808652600b85528386208054831684179055308087528487208054841685179055610140519098168087528487208054841685179055978652600c90945282852080548216831790558585528285208054821683179055958452908320805490951681179094556009805494850181559091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af90920180546001600160a01b031916909117905562000390906c13a1ab1508d490547a49000000620003e9565b6200069d565b3390565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216620004445760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b8060035f82825462000457919062000677565b90915550506001600160a01b0382165f90815260016020526040812080548392906200048590849062000677565b90915550506040518181526001600160a01b038316905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b505050565b610c5b8062002f5083390190565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200050a57607f821691505b6020821081036200052957634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620004ce575f81815260208120601f850160051c81016020861015620005575750805b601f850160051c820191505b81811015620005785782815560010162000563565b505050505050565b81516001600160401b038111156200059c576200059c620004e1565b620005b481620005ad8454620004f5565b846200052f565b602080601f831160018114620005ea575f8415620005d25750858301515b5f19600386901b1c1916600185901b17855562000578565b5f85815260208120601f198616915b828110156200061a57888601518255948401946001909101908401620005f9565b50858210156200063857878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f6020828403121562000659575f80fd5b81516001600160a01b038116811462000670575f80fd5b9392505050565b808201808211156200069757634e487b7160e01b5f52601160045260245ffd5b92915050565b60805160a05160c05160e05161010051610120516101405161016051610180516127e46200076c5f395f81816106bc01528181611e3501528181611eec01528181611f2801528181611fce015261202901525f818161043e0152610ffa01525f818161026f01526119f801525f611bed01525f81816122aa01528181612302015261235a01525f81816117b0015261181401525f818161062c015281816117d6015261232601525f818161078a015261237e01525f81816105c90152818161183501526122ce01526127e45ff3fe60806040526004361061022b575f3560e01c806370a0823111610129578063a457c2d7116100a8578063dd62ed3e1161006d578063dd62ed3e146106fd578063f0f2c9ef1461071c578063f2fde38b1461073b578063f9a580f81461075a578063fce589d814610779575f80fd5b8063a457c2d71461064e578063a9059cbb1461066d578063acc2166a1461068c578063b9b6f9b6146106ab578063cc274b29146106de575f80fd5b80638a8c523c116100ee5780638a8c523c146105a45780638b424267146105b85780638da5cb5b146105eb57806395d89b411461060757806398118cb41461061b575f80fd5b806370a08231146104f0578063715018a6146105245780637803deaa14610538578063866083261461055757806388f8202014610576575f80fd5b8063244ce7db116101b55780634c62f0931161017a5780634c62f0931461042d5780635342acb4146104605780635c9a05b81461048e57806360e71962146104bc57806364dfd203146104d1575f80fd5b8063244ce7db146103975780632d48e896146103b6578063313ce567146103d557806339509351146103f05780634ada218b1461040f575f80fd5b80630a2d140c116101fb5780630a2d140c146102f957806318160ddd1461031a5780631b7a1fb21461032e5780631ba765401461034d57806323b872dd14610378575f80fd5b80630445b66714610236578063062287491461025e57806306fdde03146102a9578063095ea7b3146102ca575f80fd5b3661023257005b5f80fd5b348015610241575f80fd5b5061024b60075481565b6040519081526020015b60405180910390f35b348015610269575f80fd5b506102917f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610255565b3480156102b4575f80fd5b506102bd6107ac565b60405161025591906123c6565b3480156102d5575f80fd5b506102e96102e4366004612425565b61083c565b6040519015158152602001610255565b348015610304575f80fd5b5061031861031336600461245e565b610855565b005b348015610325575f80fd5b5060035461024b565b348015610339575f80fd5b5061029161034836600461247e565b6108b3565b348015610358575f80fd5b5061024b610367366004612495565b600e6020525f908152604090205481565b348015610383575f80fd5b506102e96103923660046124b0565b6108db565b3480156103a2575f80fd5b506103186103b136600461247e565b6108fe565b3480156103c1575f80fd5b506103186103d03660046124ee565b610992565b3480156103e0575f80fd5b5060405160128152602001610255565b3480156103fb575f80fd5b506102e961040a366004612425565b610a83565b34801561041a575f80fd5b506008546102e990610100900460ff1681565b348015610438575f80fd5b506102917f000000000000000000000000000000000000000000000000000000000000000081565b34801561046b575f80fd5b506102e961047a366004612495565b600b6020525f908152604090205460ff1681565b348015610499575f80fd5b506102e96104a8366004612495565b600d6020525f908152604090205460ff1681565b3480156104c7575f80fd5b5061024b60065481565b3480156104dc575f80fd5b506103186104eb36600461250e565b610aa4565b3480156104fb575f80fd5b5061024b61050a366004612495565b6001600160a01b03165f9081526001602052604090205490565b34801561052f575f80fd5b50610318610ba0565b348015610543575f80fd5b5061031861055236600461250e565b610bb3565b348015610562575f80fd5b506008546102e99062010000900460ff1681565b348015610581575f80fd5b506102e9610590366004612495565b600c6020525f908152604090205460ff1681565b3480156105af575f80fd5b50610318610d16565b3480156105c3575f80fd5b5061024b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105f6575f80fd5b505f546001600160a01b0316610291565b348015610612575f80fd5b506102bd610daf565b348015610626575f80fd5b5061024b7f000000000000000000000000000000000000000000000000000000000000000081565b348015610659575f80fd5b506102e9610668366004612425565b610dbe565b348015610678575f80fd5b506102e9610687366004612425565b610e38565b348015610697575f80fd5b50600a54610291906001600160a01b031681565b3480156106b6575f80fd5b506102917f000000000000000000000000000000000000000000000000000000000000000081565b3480156106e9575f80fd5b506103186106f836600461247e565b610e45565b348015610708575f80fd5b5061024b610717366004612541565b610f4c565b348015610727575f80fd5b50610318610736366004612578565b610f76565b348015610746575f80fd5b50610318610755366004612495565b611363565b348015610765575f80fd5b50610318610774366004612425565b6113dc565b348015610784575f80fd5b5061024b7f000000000000000000000000000000000000000000000000000000000000000081565b6060600480546107bb906125b3565b80601f01602080910402602001604051908101604052809291908181526020018280546107e7906125b3565b80156108325780601f1061080957610100808354040283529160200191610832565b820191905f5260205f20905b81548152906001019060200180831161081557829003601f168201915b5050505050905090565b5f336108498185856114e6565b60019150505b92915050565b61085d611609565b60088054821515620100000262ff0000199091161790556040517fb38aef214af8a01121ddda7dd915117d0bbe821c96b4ab3915f4cee420bb54d9906108a890831515815260200190565b60405180910390a150565b600981815481106108c2575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f336108e8858285611662565b6108f38585856116da565b506001949350505050565b610906611609565b620b71b0811061095d5760405162461bcd60e51b815260206004820152601960248201527f4761732069732067726561746572207468616e206c696d69740000000000000060448201526064015b60405180910390fd5b60068190556040518181527f5f0cf7d11c1aaf2b53b91892382eaee789338051f9fcecf528ca006d062bfba8906020016108a8565b61099a611609565b5f81116109e95760405162461bcd60e51b815260206004820152601f60248201527f4d696e2e20646973747269627574696f6e2063616e2774206265207a65726f006044820152606401610954565b600a546040516316a4744b60e11b815260048101849052602481018390526001600160a01b0390911690632d48e896906044015f604051808303815f87803b158015610a33575f80fd5b505af1925050508015610a44575060015b5060408051838152602081018390527f4bee245ad45dacfa3feb4cc8a61ace735c47b485fb8a399ce9e3f6c87aade41891015b60405180910390a15050565b5f33610849818585610a958383610f4c565b610a9f91906125ff565b6114e6565b610aac611609565b6001600160a01b038216610b025760405162461bcd60e51b815260206004820152601d60248201527f57616c6c65742061646472657373206973206e6f7420636f72726563740000006044820152606401610954565b6001600160a01b0382165f908152600b602052604090205481151560ff909116151503610b415760405162461bcd60e51b815260040161095490612612565b6001600160a01b0382165f818152600b6020908152604091829020805460ff191685151590811790915591519182527f793188c766da601299dd85f7f21348a41b2cb4cadf893f2155f210d64fc049b891015b60405180910390a25050565b610ba8611609565b610bb15f611b02565b565b610bbb611609565b6001600160a01b038216610c005760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610954565b6001600160a01b0382165f908152600c602052604090205481151560ff909116151503610c3f5760405162461bcd60e51b815260040161095490612612565b6001600160a01b0382165f908152600c60205260409020805460ff19168215801591909117909155610cd057600a54604051630a5b654b60e11b81526001600160a01b0384811660048301525f6024830152909116906314b6ca96906044015f604051808303815f87803b158015610cb5575f80fd5b505af1925050508015610cc6575060015b15610cd957610cd9565b610cd982611b51565b816001600160a01b03167f21dfac5ff6a7cc530320d4cb002a96edf0c323b87dbe9eb9a4c39a5c3a62cbb982604051610b94911515815260200190565b610d1e611609565b600854610100900460ff1615610d765760405162461bcd60e51b815260206004820152601760248201527f54726164696e6720616c726561647920656e61626c65640000000000000000006044820152606401610954565b6008805461ff0019166101001790556040517f799663458a5ef2936f7fa0c99b3336c69c25890f82974f04e811e5bb359186c7905f90a1565b6060600580546107bb906125b3565b5f3381610dcb8286610f4c565b905083811015610e2b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610954565b6108f382868684036114e6565b5f336108498185856116da565b610e4d611609565b600354811115610eaf5760405162461bcd60e51b815260206004820152602760248201527f416d6f756e742063616e6e6f74206265206f7665722074686520746f74616c2060448201526639bab838363c9760c91b6064820152608401610954565b683635c9adc5dea00000811015610f175760405162461bcd60e51b815260206004820152602660248201527f4d696e696d756d2060313030306020746f6b656e2070657220737761702072656044820152651c5d5a5c995960d21b6064820152608401610954565b60078190556040518181527f18ff2fc8464635e4f668567019152095047e34d7a2ab4b97661ba4dc7fd06476906020016108a8565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205490565b610f7e611609565b6001600160a01b0383165f908152600d602052604090205482151560ff909116151503610ff85760405162461bcd60e51b815260206004820152602260248201527f5061697220697320616c72656164792073657420746f20746861742073746174604482015261757360f01b6064820152608401610954565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036110855760405162461bcd60e51b8152602060048201526024808201527f43616e2774207570646174652074686520737461747573206f66206d61696e206044820152633830b4b960e11b6064820152608401610954565b81156111b25761109483611ceb565b6110d95760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103634b8bab4b234ba3c903830b4b960511b6044820152606401610954565b5f81116111285760405162461bcd60e51b815260206004820152601f60248201527f5368617265206d7573742062652067726561746572207468616e207a65726f006044820152606401610954565b60098054600181019091557f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b0385166001600160a01b031990911681179091555f908152600d60209081526040808320805486151560ff199182168117909255600c845282852080549091169091179055600e9091529020819055611319565b6001600160a01b0383165f908152600d602052604090205460ff1615611319575f5b6009548110156112d257836001600160a01b0316600982815481106111fb576111fb612659565b5f918252602090912001546001600160a01b0316036112c057600980546112249060019061266d565b8154811061123457611234612659565b5f91825260209091200154600980546001600160a01b03909216918390811061125f5761125f612659565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550600980548061129b5761129b612680565b5f8281526020902081015f1990810180546001600160a01b03191690550190556112d2565b806112ca81612694565b9150506111d4565b506001600160a01b0383165f908152600e60209081526040808320839055600d8252808320805486151560ff199182168117909255600c9093529220805490911690911790555b826001600160a01b03167f4bf69fee59f1751bf6064f46595c52d722796b529aca2b5a7b6d1ac6a8f8b03183604051611356911515815260200190565b60405180910390a2505050565b61136b611609565b6001600160a01b0381166113d05760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610954565b6113d981611b02565b50565b6113e4611609565b6001600160a01b0382165f908152600d602052604090205460ff1661144b5760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420612072656769737465726564206c69717569646974792070616972006044820152606401610954565b5f811161149a5760405162461bcd60e51b815260206004820152601f60248201527f5368617265206d7573742062652067726561746572207468616e207a65726f006044820152606401610954565b6001600160a01b0382165f818152600e602052604090819020839055517fd678ae6319b7a48589104de503993168ab3f547fddc47d3e725f3062325414f190610b949084815260200190565b6001600160a01b0383166115485760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610954565b6001600160a01b0382166115a95760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610954565b6001600160a01b038381165f8181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f546001600160a01b03163314610bb15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610954565b5f61166d8484610f4c565b90505f1981146116d457818110156116c75760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610954565b6116d484848484036114e6565b50505050565b600854610100900460ff16611752575f546001600160a01b038481169116148061171057505f546001600160a01b038381169116145b6117525760405162461bcd60e51b8152602060048201526013602482015272151c98591a5b99c81b9bdd08195b98589b1959606a1b6044820152606401610954565b60085460ff1615801561177c57506001600160a01b0382165f908152600d602052604090205460ff165b1561193357305f908152600160205260409020546007548110611931576008805460ff191660011790556007545f906002907f0000000000000000000000000000000000000000000000000000000000000000906117fb907f0000000000000000000000000000000000000000000000000000000000000000906126ac565b61180591906126c3565b61180f91906126c3565b90505f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060075461186191906126ac565b61186b91906126c3565b90505f61187882846125ff565b905061188381611de0565b475f8261189086846126ac565b61189a91906126c3565b90505f6118a7828461266d565b905081156118b9576118b98683611fc8565b801561192057600a5f9054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b15801561190c575f80fd5b505af19350505050801561191e575060015b505b50506008805460ff19169055505050505b505b6001600160a01b0383165f908152600b602052604090205460ff168061197057506001600160a01b0382165f908152600b602052604090205460ff165b806119b657506001600160a01b0383165f908152600d602052604090205460ff161580156119b657506001600160a01b0382165f908152600d602052604090205460ff16155b156119cb576119c68383836120d9565b611a3e565b5f806119d6836122a5565b909250905080156119ec576119ec8530836120d9565b8115611a1d57611a1d857f0000000000000000000000000000000000000000000000000000000000000000846120d9565b611a3b8585611a2c85856125ff565b611a36908761266d565b6120d9565b50505b6001600160a01b0383165f908152600c602052604090205460ff16611a6657611a6683611b51565b6001600160a01b0382165f908152600c602052604090205460ff16611a8e57611a8e82611b51565b60085462010000900460ff1615611afd57600a546006546040516001624d3b8760e01b031981526001600160a01b039092169163ffb2c47991611ad79160040190815260200190565b5f604051808303815f87803b158015611aee575f80fd5b505af19250505080156116d457505b505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381165f908152600c602052604090205460ff1615611b745750565b6001600160a01b0381165f90815260016020526040812054905b600954811015611c8c575f60098281548110611bac57611bac612659565b5f918252602080832091909101546001600160a01b03908116808452600e9092526040928390205492516370a0823160e01b815290871660048201529092507f0000000000000000000000000000000000000000000000000000000000000000919083906370a0823190602401602060405180830381865afa158015611c34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c5891906126e2565b611c6291906126ac565b611c6c91906126c3565b611c7690846125ff565b9250508080611c8490612694565b915050611b8e565b50600a54604051630a5b654b60e11b81526001600160a01b03848116600483015260248201849052909116906314b6ca96906044015f604051808303815f87803b158015611cd8575f80fd5b505af1925050508015611afd57505b5050565b5f816001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611d46575060408051601f3d908101601f19168201909252611d43918101906126f9565b60015b611d5157505f919050565b5f836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d8e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db291906126f9565b90506001600160a01b038216301480611dd357506001600160a01b03811630145b949350505050565b919050565b6040805160028082526060820183525f9260208301908036833701905050905030815f81518110611e1357611e13612659565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eb391906126f9565b81600181518110611ec657611ec6612659565b60200260200101906001600160a01b031690816001600160a01b031681525050611f11307f0000000000000000000000000000000000000000000000000000000000000000846114e6565b60405163791ac94760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063791ac94790611f659085905f90869030904290600401612714565b5f604051808303815f87803b158015611f7c575f80fd5b505af1925050508015611f8d575060015b611ce7576040518281527ff9e10ddceffcb10b96e8833202366240699b814c91f371ddd9befa3aee9bc60f9060200160405180910390a15050565b611ff3307f0000000000000000000000000000000000000000000000000000000000000000846114e6565b60405163f305d71960e01b81523060048201819052602482018490525f60448301819052606483015260848201524260a48201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f305d71990839060c40160606040518083038185885af193505050508015612098575060408051601f3d908101601f1916820190925261209591810190612783565b60015b6120d25760408051838152602081018390527f5da0a291cd4a66542c9b71428cd223b8efd210676ebf390e5dc0092e50d15f919101610a77565b5050505050565b6001600160a01b03831661213d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610954565b6001600160a01b03821661219f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610954565b6001600160a01b0383165f90815260016020526040902054818110156122165760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610954565b6001600160a01b038085165f9081526001602052604080822085850390559185168152908120805484929061224c9084906125ff565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161229891815260200190565b60405180910390a36116d4565b5f80807f00000000000000000000000000000000000000000000000000000000000000006122f37f0000000000000000000000000000000000000000000000000000000000000000866126ac565b6122fd91906126c3565b90505f7f000000000000000000000000000000000000000000000000000000000000000061234b7f0000000000000000000000000000000000000000000000000000000000000000876126ac565b61235591906126c3565b90505f7f00000000000000000000000000000000000000000000000000000000000000006123a37f0000000000000000000000000000000000000000000000000000000000000000886126ac565b6123ad91906126c3565b9050806123ba83856125ff565b94509450505050915091565b5f6020808352835180828501525f5b818110156123f1578581018301518582016040015282016123d5565b505f604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b03811681146113d9575f80fd5b5f8060408385031215612436575f80fd5b823561244181612411565b946020939093013593505050565b80358015158114611ddb575f80fd5b5f6020828403121561246e575f80fd5b6124778261244f565b9392505050565b5f6020828403121561248e575f80fd5b5035919050565b5f602082840312156124a5575f80fd5b813561247781612411565b5f805f606084860312156124c2575f80fd5b83356124cd81612411565b925060208401356124dd81612411565b929592945050506040919091013590565b5f80604083850312156124ff575f80fd5b50508035926020909101359150565b5f806040838503121561251f575f80fd5b823561252a81612411565b91506125386020840161244f565b90509250929050565b5f8060408385031215612552575f80fd5b823561255d81612411565b9150602083013561256d81612411565b809150509250929050565b5f805f6060848603121561258a575f80fd5b833561259581612411565b92506125a36020850161244f565b9150604084013590509250925092565b600181811c908216806125c757607f821691505b6020821081036125e557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561084f5761084f6125eb565b60208082526027908201527f57616c6c657420697320616c7265616479207468652076616c7565206f6620276040820152667374617475732760c81b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b8181038181111561084f5761084f6125eb565b634e487b7160e01b5f52603160045260245ffd5b5f600182016126a5576126a56125eb565b5060010190565b808202811582820484141761084f5761084f6125eb565b5f826126dd57634e487b7160e01b5f52601260045260245ffd5b500490565b5f602082840312156126f2575f80fd5b5051919050565b5f60208284031215612709575f80fd5b815161247781612411565b5f60a082018783526020878185015260a0604085015281875180845260c08601915082890193505f5b818110156127625784516001600160a01b03168352938301939183019160010161273d565b50506001600160a01b03969096166060850152505050608001529392505050565b5f805f60608486031215612795575f80fd5b835192506020840151915060408401519050925092509256fea2646970667358221220a1233dfb8affacd3db35f63b1dfe5a21456f8da90abc062358b380c680d9350a64736f6c6343000814003360806040526ec097ce7bc90715b34b9f1000000000600a55600a600b556402540be400600c55348015610030575f80fd5b5060015f81905580546001600160a01b03191633179055610c07806100545f395ff3fe6080604052600436106100f2575f3560e01c8063b88a802f11610087578063e2d2e21911610057578063e2d2e2191461028a578063efca2eed1461029f578063ffb2c479146102b4578063ffd49c84146102d3575f80fd5b8063b88a802f146101ee578063ce7c2ac214610202578063d0e30db014610257578063d4fda1f21461025f575f80fd5b80633a98ef39116100c25780633a98ef39146101845780634fab0ae81461019957806366817df5146101ae578063997664d7146101d9575f80fd5b806311ce023d146100fd57806314b6ca961461012557806328fd3198146101465780632d48e89614610165575f80fd5b366100f957005b5f80fd5b348015610108575f80fd5b50610112600a5481565b6040519081526020015b60405180910390f35b348015610130575f80fd5b5061014461013f366004610a82565b6102e8565b005b348015610151575f80fd5b50610112610160366004610aaa565b610474565b348015610170575f80fd5b5061014461017f366004610aca565b6104fa565b34801561018f575f80fd5b5061011260065481565b3480156101a4575f80fd5b50610112600c5481565b3480156101b9575f80fd5b506101126101c8366004610aaa565b60046020525f908152604090205481565b3480156101e4575f80fd5b5061011260075481565b3480156101f9575f80fd5b5061014461056b565b34801561020d575f80fd5b5061023c61021c366004610aaa565b60056020525f908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161011c565b6101446105dd565b34801561026a575f80fd5b50610112610279366004610aaa565b60036020525f908152604090205481565b348015610295575f80fd5b5061011260095481565b3480156102aa575f80fd5b5061011260085481565b3480156102bf575f80fd5b506101446102ce366004610aea565b610684565b3480156102de575f80fd5b50610112600b5481565b6001546001600160a01b0316331461031b5760405162461bcd60e51b815260040161031290610b01565b60405180910390fd5b6001600160a01b0382165f90815260056020526040902054156103415761034182610794565b5f8111801561036557506001600160a01b0382165f90815260056020526040902054155b156103ca57600280546001600160a01b0384165f818152600360205260408120839055600183018455929092527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b03191690911790556103fc565b801580156103ee57506001600160a01b0382165f9081526005602052604090205415155b156103fc576103fc826108f1565b6001600160a01b0382165f90815260056020526040902054600654829161042291610b35565b61042c9190610b48565b6006556001600160a01b0382165f90815260056020526040902081905561045281610a01565b6001600160a01b039092165f9081526005602052604090206001019190915550565b6001600160a01b0381165f90815260056020526040812054810361049957505f919050565b6001600160a01b0382165f908152600560205260408120546104ba90610a01565b6001600160a01b0384165f908152600560205260409020600101549091508082116104e857505f9392505050565b6104f28183610b35565b949350505050565b6001546001600160a01b031633146105245760405162461bcd60e51b815260040161031290610b01565b600b829055600c81905560408051838152602081018390527f7d38de579bb682aa05ace7e32d15f88df69a3a53f6f89fcd0236f93fcc7e6362910160405180910390a15050565b60025f54036105bc5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610312565b60025f556105c933610a23565b156105d7576105d733610794565b60015f55565b6001546001600160a01b031633146106075760405162461bcd60e51b815260040161031290610b01565b3460075f8282546106189190610b48565b9091555050600654600a5461062e903490610b5b565b6106389190610b72565b60095f8282546106489190610b48565b909155505060405134815233907f61f49175fe1d0957ca728302166505f7a310d3088ac3b748e92533f9f3458e399060200160405180910390a2565b6001546001600160a01b031633146106ae5760405162461bcd60e51b815260040161031290610b01565b6002545f8190036106bd575050565b5f805a90505f5b84831080156106d257508381105b1561078d5783600d54106106e5575f600d555b6107166002600d54815481106106fd576106fd610b91565b5f918252602090912001546001600160a01b0316610a23565b1561074c5761074c6002600d548154811061073357610733610b91565b5f918252602090912001546001600160a01b0316610794565b5a6107578385610b48565b6107619190610b35565b92505a600d80549193505f61077583610ba5565b9190505550808061078590610ba5565b9150506106c4565b5050505050565b6001600160a01b0381165f9081526005602052604081205490036107b55750565b5f6107bf82610474565b905080156108ed575f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610810576040519150601f19603f3d011682016040523d82523d5f602084013e610815565b606091505b5050905080156108eb578160085f8282546108309190610b48565b90915550506001600160a01b0383165f9081526004602090815260408083204290556005909152902060020154610868908390610b48565b6001600160a01b0384165f90815260056020526040902060028101919091555461089190610a01565b6001600160a01b0384165f81815260056020526040908190206001019290925590517f84fcdd4a7f507f2206dd50958e7473061bf941f91791c6ffaf74033a07c82f12906108e29085815260200190565b60405180910390a25b505b5050565b6002805461090190600190610b35565b8154811061091157610911610b91565b5f9182526020808320909101546001600160a01b038481168452600390925260409092205460028054929093169291811061094e5761094e610b91565b5f91825260208083209190910180546001600160a01b0319166001600160a01b0394851617905591831681526003918290526040812054600280549193929161099990600190610b35565b815481106109a9576109a9610b91565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205560028054806109de576109de610bbd565b5f8281526020902081015f1990810180546001600160a01b031916905501905550565b5f600a5460095483610a139190610b5b565b610a1d9190610b72565b92915050565b600b546001600160a01b0382165f9081526004602052604081205490914291610a4c9190610b48565b108015610a1d5750600c54610a6083610474565b1192915050565b80356001600160a01b0381168114610a7d575f80fd5b919050565b5f8060408385031215610a93575f80fd5b610a9c83610a67565b946020939093013593505050565b5f60208284031215610aba575f80fd5b610ac382610a67565b9392505050565b5f8060408385031215610adb575f80fd5b50508035926020909101359150565b5f60208284031215610afa575f80fd5b5035919050565b60208082526006908201526510aa37b5b2b760d11b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a1d57610a1d610b21565b80820180821115610a1d57610a1d610b21565b8082028115828204841417610a1d57610a1d610b21565b5f82610b8c57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f60018201610bb657610bb6610b21565b5060010190565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220398e9bc5cac124f7d8fddb11f860be4dcdf8f7289c980fb53876f982415d23b764736f6c63430008140033
Deployed ByteCode
0x60806040526004361061022b575f3560e01c806370a0823111610129578063a457c2d7116100a8578063dd62ed3e1161006d578063dd62ed3e146106fd578063f0f2c9ef1461071c578063f2fde38b1461073b578063f9a580f81461075a578063fce589d814610779575f80fd5b8063a457c2d71461064e578063a9059cbb1461066d578063acc2166a1461068c578063b9b6f9b6146106ab578063cc274b29146106de575f80fd5b80638a8c523c116100ee5780638a8c523c146105a45780638b424267146105b85780638da5cb5b146105eb57806395d89b411461060757806398118cb41461061b575f80fd5b806370a08231146104f0578063715018a6146105245780637803deaa14610538578063866083261461055757806388f8202014610576575f80fd5b8063244ce7db116101b55780634c62f0931161017a5780634c62f0931461042d5780635342acb4146104605780635c9a05b81461048e57806360e71962146104bc57806364dfd203146104d1575f80fd5b8063244ce7db146103975780632d48e896146103b6578063313ce567146103d557806339509351146103f05780634ada218b1461040f575f80fd5b80630a2d140c116101fb5780630a2d140c146102f957806318160ddd1461031a5780631b7a1fb21461032e5780631ba765401461034d57806323b872dd14610378575f80fd5b80630445b66714610236578063062287491461025e57806306fdde03146102a9578063095ea7b3146102ca575f80fd5b3661023257005b5f80fd5b348015610241575f80fd5b5061024b60075481565b6040519081526020015b60405180910390f35b348015610269575f80fd5b506102917f000000000000000000000000000000000000000000000000000000000000036981565b6040516001600160a01b039091168152602001610255565b3480156102b4575f80fd5b506102bd6107ac565b60405161025591906123c6565b3480156102d5575f80fd5b506102e96102e4366004612425565b61083c565b6040519015158152602001610255565b348015610304575f80fd5b5061031861031336600461245e565b610855565b005b348015610325575f80fd5b5060035461024b565b348015610339575f80fd5b5061029161034836600461247e565b6108b3565b348015610358575f80fd5b5061024b610367366004612495565b600e6020525f908152604090205481565b348015610383575f80fd5b506102e96103923660046124b0565b6108db565b3480156103a2575f80fd5b506103186103b136600461247e565b6108fe565b3480156103c1575f80fd5b506103186103d03660046124ee565b610992565b3480156103e0575f80fd5b5060405160128152602001610255565b3480156103fb575f80fd5b506102e961040a366004612425565b610a83565b34801561041a575f80fd5b506008546102e990610100900460ff1681565b348015610438575f80fd5b506102917f0000000000000000000000007114ead44cab77ca9a136d2663a6e500de8bd0ef81565b34801561046b575f80fd5b506102e961047a366004612495565b600b6020525f908152604090205460ff1681565b348015610499575f80fd5b506102e96104a8366004612495565b600d6020525f908152604090205460ff1681565b3480156104c7575f80fd5b5061024b60065481565b3480156104dc575f80fd5b506103186104eb36600461250e565b610aa4565b3480156104fb575f80fd5b5061024b61050a366004612495565b6001600160a01b03165f9081526001602052604090205490565b34801561052f575f80fd5b50610318610ba0565b348015610543575f80fd5b5061031861055236600461250e565b610bb3565b348015610562575f80fd5b506008546102e99062010000900460ff1681565b348015610581575f80fd5b506102e9610590366004612495565b600c6020525f908152604090205460ff1681565b3480156105af575f80fd5b50610318610d16565b3480156105c3575f80fd5b5061024b7f000000000000000000000000000000000000000000000000000000000000015e81565b3480156105f6575f80fd5b505f546001600160a01b0316610291565b348015610612575f80fd5b506102bd610daf565b348015610626575f80fd5b5061024b7f000000000000000000000000000000000000000000000000000000000000006481565b348015610659575f80fd5b506102e9610668366004612425565b610dbe565b348015610678575f80fd5b506102e9610687366004612425565b610e38565b348015610697575f80fd5b50600a54610291906001600160a01b031681565b3480156106b6575f80fd5b506102917f000000000000000000000000165c3410fc91ef562c50559f7d2289febed552d981565b3480156106e9575f80fd5b506103186106f836600461247e565b610e45565b348015610708575f80fd5b5061024b610717366004612541565b610f4c565b348015610727575f80fd5b50610318610736366004612578565b610f76565b348015610746575f80fd5b50610318610755366004612495565b611363565b348015610765575f80fd5b50610318610774366004612425565b6113dc565b348015610784575f80fd5b5061024b7f000000000000000000000000000000000000000000000000000000000000003281565b6060600480546107bb906125b3565b80601f01602080910402602001604051908101604052809291908181526020018280546107e7906125b3565b80156108325780601f1061080957610100808354040283529160200191610832565b820191905f5260205f20905b81548152906001019060200180831161081557829003601f168201915b5050505050905090565b5f336108498185856114e6565b60019150505b92915050565b61085d611609565b60088054821515620100000262ff0000199091161790556040517fb38aef214af8a01121ddda7dd915117d0bbe821c96b4ab3915f4cee420bb54d9906108a890831515815260200190565b60405180910390a150565b600981815481106108c2575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f336108e8858285611662565b6108f38585856116da565b506001949350505050565b610906611609565b620b71b0811061095d5760405162461bcd60e51b815260206004820152601960248201527f4761732069732067726561746572207468616e206c696d69740000000000000060448201526064015b60405180910390fd5b60068190556040518181527f5f0cf7d11c1aaf2b53b91892382eaee789338051f9fcecf528ca006d062bfba8906020016108a8565b61099a611609565b5f81116109e95760405162461bcd60e51b815260206004820152601f60248201527f4d696e2e20646973747269627574696f6e2063616e2774206265207a65726f006044820152606401610954565b600a546040516316a4744b60e11b815260048101849052602481018390526001600160a01b0390911690632d48e896906044015f604051808303815f87803b158015610a33575f80fd5b505af1925050508015610a44575060015b5060408051838152602081018390527f4bee245ad45dacfa3feb4cc8a61ace735c47b485fb8a399ce9e3f6c87aade41891015b60405180910390a15050565b5f33610849818585610a958383610f4c565b610a9f91906125ff565b6114e6565b610aac611609565b6001600160a01b038216610b025760405162461bcd60e51b815260206004820152601d60248201527f57616c6c65742061646472657373206973206e6f7420636f72726563740000006044820152606401610954565b6001600160a01b0382165f908152600b602052604090205481151560ff909116151503610b415760405162461bcd60e51b815260040161095490612612565b6001600160a01b0382165f818152600b6020908152604091829020805460ff191685151590811790915591519182527f793188c766da601299dd85f7f21348a41b2cb4cadf893f2155f210d64fc049b891015b60405180910390a25050565b610ba8611609565b610bb15f611b02565b565b610bbb611609565b6001600160a01b038216610c005760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610954565b6001600160a01b0382165f908152600c602052604090205481151560ff909116151503610c3f5760405162461bcd60e51b815260040161095490612612565b6001600160a01b0382165f908152600c60205260409020805460ff19168215801591909117909155610cd057600a54604051630a5b654b60e11b81526001600160a01b0384811660048301525f6024830152909116906314b6ca96906044015f604051808303815f87803b158015610cb5575f80fd5b505af1925050508015610cc6575060015b15610cd957610cd9565b610cd982611b51565b816001600160a01b03167f21dfac5ff6a7cc530320d4cb002a96edf0c323b87dbe9eb9a4c39a5c3a62cbb982604051610b94911515815260200190565b610d1e611609565b600854610100900460ff1615610d765760405162461bcd60e51b815260206004820152601760248201527f54726164696e6720616c726561647920656e61626c65640000000000000000006044820152606401610954565b6008805461ff0019166101001790556040517f799663458a5ef2936f7fa0c99b3336c69c25890f82974f04e811e5bb359186c7905f90a1565b6060600580546107bb906125b3565b5f3381610dcb8286610f4c565b905083811015610e2b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610954565b6108f382868684036114e6565b5f336108498185856116da565b610e4d611609565b600354811115610eaf5760405162461bcd60e51b815260206004820152602760248201527f416d6f756e742063616e6e6f74206265206f7665722074686520746f74616c2060448201526639bab838363c9760c91b6064820152608401610954565b683635c9adc5dea00000811015610f175760405162461bcd60e51b815260206004820152602660248201527f4d696e696d756d2060313030306020746f6b656e2070657220737761702072656044820152651c5d5a5c995960d21b6064820152608401610954565b60078190556040518181527f18ff2fc8464635e4f668567019152095047e34d7a2ab4b97661ba4dc7fd06476906020016108a8565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205490565b610f7e611609565b6001600160a01b0383165f908152600d602052604090205482151560ff909116151503610ff85760405162461bcd60e51b815260206004820152602260248201527f5061697220697320616c72656164792073657420746f20746861742073746174604482015261757360f01b6064820152608401610954565b7f0000000000000000000000007114ead44cab77ca9a136d2663a6e500de8bd0ef6001600160a01b0316836001600160a01b0316036110855760405162461bcd60e51b8152602060048201526024808201527f43616e2774207570646174652074686520737461747573206f66206d61696e206044820152633830b4b960e11b6064820152608401610954565b81156111b25761109483611ceb565b6110d95760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103634b8bab4b234ba3c903830b4b960511b6044820152606401610954565b5f81116111285760405162461bcd60e51b815260206004820152601f60248201527f5368617265206d7573742062652067726561746572207468616e207a65726f006044820152606401610954565b60098054600181019091557f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b0385166001600160a01b031990911681179091555f908152600d60209081526040808320805486151560ff199182168117909255600c845282852080549091169091179055600e9091529020819055611319565b6001600160a01b0383165f908152600d602052604090205460ff1615611319575f5b6009548110156112d257836001600160a01b0316600982815481106111fb576111fb612659565b5f918252602090912001546001600160a01b0316036112c057600980546112249060019061266d565b8154811061123457611234612659565b5f91825260209091200154600980546001600160a01b03909216918390811061125f5761125f612659565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550600980548061129b5761129b612680565b5f8281526020902081015f1990810180546001600160a01b03191690550190556112d2565b806112ca81612694565b9150506111d4565b506001600160a01b0383165f908152600e60209081526040808320839055600d8252808320805486151560ff199182168117909255600c9093529220805490911690911790555b826001600160a01b03167f4bf69fee59f1751bf6064f46595c52d722796b529aca2b5a7b6d1ac6a8f8b03183604051611356911515815260200190565b60405180910390a2505050565b61136b611609565b6001600160a01b0381166113d05760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610954565b6113d981611b02565b50565b6113e4611609565b6001600160a01b0382165f908152600d602052604090205460ff1661144b5760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420612072656769737465726564206c69717569646974792070616972006044820152606401610954565b5f811161149a5760405162461bcd60e51b815260206004820152601f60248201527f5368617265206d7573742062652067726561746572207468616e207a65726f006044820152606401610954565b6001600160a01b0382165f818152600e602052604090819020839055517fd678ae6319b7a48589104de503993168ab3f547fddc47d3e725f3062325414f190610b949084815260200190565b6001600160a01b0383166115485760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610954565b6001600160a01b0382166115a95760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610954565b6001600160a01b038381165f8181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f546001600160a01b03163314610bb15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610954565b5f61166d8484610f4c565b90505f1981146116d457818110156116c75760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610954565b6116d484848484036114e6565b50505050565b600854610100900460ff16611752575f546001600160a01b038481169116148061171057505f546001600160a01b038381169116145b6117525760405162461bcd60e51b8152602060048201526013602482015272151c98591a5b99c81b9bdd08195b98589b1959606a1b6044820152606401610954565b60085460ff1615801561177c57506001600160a01b0382165f908152600d602052604090205460ff165b1561193357305f908152600160205260409020546007548110611931576008805460ff191660011790556007545f906002907f00000000000000000000000000000000000000000000000000000000000001c2906117fb907f0000000000000000000000000000000000000000000000000000000000000064906126ac565b61180591906126c3565b61180f91906126c3565b90505f7f00000000000000000000000000000000000000000000000000000000000001c27f000000000000000000000000000000000000000000000000000000000000015e60075461186191906126ac565b61186b91906126c3565b90505f61187882846125ff565b905061188381611de0565b475f8261189086846126ac565b61189a91906126c3565b90505f6118a7828461266d565b905081156118b9576118b98683611fc8565b801561192057600a5f9054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b15801561190c575f80fd5b505af19350505050801561191e575060015b505b50506008805460ff19169055505050505b505b6001600160a01b0383165f908152600b602052604090205460ff168061197057506001600160a01b0382165f908152600b602052604090205460ff165b806119b657506001600160a01b0383165f908152600d602052604090205460ff161580156119b657506001600160a01b0382165f908152600d602052604090205460ff16155b156119cb576119c68383836120d9565b611a3e565b5f806119d6836122a5565b909250905080156119ec576119ec8530836120d9565b8115611a1d57611a1d857f0000000000000000000000000000000000000000000000000000000000000369846120d9565b611a3b8585611a2c85856125ff565b611a36908761266d565b6120d9565b50505b6001600160a01b0383165f908152600c602052604090205460ff16611a6657611a6683611b51565b6001600160a01b0382165f908152600c602052604090205460ff16611a8e57611a8e82611b51565b60085462010000900460ff1615611afd57600a546006546040516001624d3b8760e01b031981526001600160a01b039092169163ffb2c47991611ad79160040190815260200190565b5f604051808303815f87803b158015611aee575f80fd5b505af19250505080156116d457505b505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381165f908152600c602052604090205460ff1615611b745750565b6001600160a01b0381165f90815260016020526040812054905b600954811015611c8c575f60098281548110611bac57611bac612659565b5f918252602080832091909101546001600160a01b03908116808452600e9092526040928390205492516370a0823160e01b815290871660048201529092507f0000000000000000000000000000000000000000000000000000000000000064919083906370a0823190602401602060405180830381865afa158015611c34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c5891906126e2565b611c6291906126ac565b611c6c91906126c3565b611c7690846125ff565b9250508080611c8490612694565b915050611b8e565b50600a54604051630a5b654b60e11b81526001600160a01b03848116600483015260248201849052909116906314b6ca96906044015f604051808303815f87803b158015611cd8575f80fd5b505af1925050508015611afd57505b5050565b5f816001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611d46575060408051601f3d908101601f19168201909252611d43918101906126f9565b60015b611d5157505f919050565b5f836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d8e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db291906126f9565b90506001600160a01b038216301480611dd357506001600160a01b03811630145b949350505050565b919050565b6040805160028082526060820183525f9260208301908036833701905050905030815f81518110611e1357611e13612659565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000165c3410fc91ef562c50559f7d2289febed552d96001600160a01b031663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eb391906126f9565b81600181518110611ec657611ec6612659565b60200260200101906001600160a01b031690816001600160a01b031681525050611f11307f000000000000000000000000165c3410fc91ef562c50559f7d2289febed552d9846114e6565b60405163791ac94760e01b81526001600160a01b037f000000000000000000000000165c3410fc91ef562c50559f7d2289febed552d9169063791ac94790611f659085905f90869030904290600401612714565b5f604051808303815f87803b158015611f7c575f80fd5b505af1925050508015611f8d575060015b611ce7576040518281527ff9e10ddceffcb10b96e8833202366240699b814c91f371ddd9befa3aee9bc60f9060200160405180910390a15050565b611ff3307f000000000000000000000000165c3410fc91ef562c50559f7d2289febed552d9846114e6565b60405163f305d71960e01b81523060048201819052602482018490525f60448301819052606483015260848201524260a48201527f000000000000000000000000165c3410fc91ef562c50559f7d2289febed552d96001600160a01b03169063f305d71990839060c40160606040518083038185885af193505050508015612098575060408051601f3d908101601f1916820190925261209591810190612783565b60015b6120d25760408051838152602081018390527f5da0a291cd4a66542c9b71428cd223b8efd210676ebf390e5dc0092e50d15f919101610a77565b5050505050565b6001600160a01b03831661213d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610954565b6001600160a01b03821661219f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610954565b6001600160a01b0383165f90815260016020526040902054818110156122165760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610954565b6001600160a01b038085165f9081526001602052604080822085850390559185168152908120805484929061224c9084906125ff565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161229891815260200190565b60405180910390a36116d4565b5f80807f00000000000000000000000000000000000000000000000000000000000027106122f37f000000000000000000000000000000000000000000000000000000000000015e866126ac565b6122fd91906126c3565b90505f7f000000000000000000000000000000000000000000000000000000000000271061234b7f0000000000000000000000000000000000000000000000000000000000000064876126ac565b61235591906126c3565b90505f7f00000000000000000000000000000000000000000000000000000000000027106123a37f0000000000000000000000000000000000000000000000000000000000000032886126ac565b6123ad91906126c3565b9050806123ba83856125ff565b94509450505050915091565b5f6020808352835180828501525f5b818110156123f1578581018301518582016040015282016123d5565b505f604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b03811681146113d9575f80fd5b5f8060408385031215612436575f80fd5b823561244181612411565b946020939093013593505050565b80358015158114611ddb575f80fd5b5f6020828403121561246e575f80fd5b6124778261244f565b9392505050565b5f6020828403121561248e575f80fd5b5035919050565b5f602082840312156124a5575f80fd5b813561247781612411565b5f805f606084860312156124c2575f80fd5b83356124cd81612411565b925060208401356124dd81612411565b929592945050506040919091013590565b5f80604083850312156124ff575f80fd5b50508035926020909101359150565b5f806040838503121561251f575f80fd5b823561252a81612411565b91506125386020840161244f565b90509250929050565b5f8060408385031215612552575f80fd5b823561255d81612411565b9150602083013561256d81612411565b809150509250929050565b5f805f6060848603121561258a575f80fd5b833561259581612411565b92506125a36020850161244f565b9150604084013590509250925092565b600181811c908216806125c757607f821691505b6020821081036125e557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561084f5761084f6125eb565b60208082526027908201527f57616c6c657420697320616c7265616479207468652076616c7565206f6620276040820152667374617475732760c81b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b8181038181111561084f5761084f6125eb565b634e487b7160e01b5f52603160045260245ffd5b5f600182016126a5576126a56125eb565b5060010190565b808202811582820484141761084f5761084f6125eb565b5f826126dd57634e487b7160e01b5f52601260045260245ffd5b500490565b5f602082840312156126f2575f80fd5b5051919050565b5f60208284031215612709575f80fd5b815161247781612411565b5f60a082018783526020878185015260a0604085015281875180845260c08601915082890193505f5b818110156127625784516001600160a01b03168352938301939183019160010161273d565b50506001600160a01b03969096166060850152505050608001529392505050565b5f805f60608486031215612795575f80fd5b835192506020840151915060408401519050925092509256fea2646970667358221220a1233dfb8affacd3db35f63b1dfe5a21456f8da90abc062358b380c680d9350a64736f6c63430008140033