Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0x8577f0fb9d709d5bebd808dddd0094fbaec667b4.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
- Contract name:
- TokenTax
- Optimization enabled
- true
- Compiler version
- v0.8.31+commit.fd3a2265
- Optimization runs
- 1
- Verified at
- 2026-04-17T02:03:22.578939Z
contracts/Tokens/TokenTaxV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "./interfaces/TokenTypes.sol";
interface IWETH_0 {
function withdraw(uint256 wad) external;
}
interface ISmartTokenFactory {
function FEE() external view returns (uint256);
function WALLET() external view returns (address);
function NEON_LP_FEE() external view returns (uint256);
function NEON_LP_RECEIVER() external view returns (address);
}
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(
address sender,
uint256 balance,
uint256 needed
);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(
address spender,
uint256 allowance,
uint256 needed
);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(
address sender,
uint256 balance,
uint256 needed,
uint256 tokenId
);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(
address owner,
address spender
) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
// lib/openzeppelin-contracts/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
interface IUniswapV2Factory {
event PairCreated(
address indexed token0,
address indexed token1,
address pair,
uint
);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(
address tokenA,
address tokenB
) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(
address tokenA,
address tokenB
) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(
address owner,
address spender
) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(
address from,
address to,
uint value
) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(
address owner,
address spender,
uint value,
uint deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(
address indexed sender,
uint amount0,
uint amount1,
address indexed to
);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves()
external
view
returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data
) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
)
external
payable
returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function swapTokensForExactETH(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapETHForExactTokens(
uint amountOut,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function quote(
uint amountA,
uint reserveA,
uint reserveB
) external pure returns (uint amountB);
function getAmountOut(
uint amountIn,
uint reserveIn,
uint reserveOut
) external pure returns (uint amountOut);
function getAmountIn(
uint amountOut,
uint reserveIn,
uint reserveOut
) external pure returns (uint amountIn);
function getAmountsOut(
uint amountIn,
address[] calldata path
) external view returns (uint[] memory amounts);
function getAmountsIn(
uint amountOut,
address[] calldata path
) external view returns (uint[] memory amounts);
}
// lib/openzeppelin-contracts/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// lib/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
// contracts/Tokens/Manager.sol
contract Manager {
// For yield tax tokens
struct UserYield {
uint256 reflectionDebt;
}
struct YieldToken {
address tokenAddress;
uint256 reflectionsPerShareAmount;
}
YieldToken[] internal yieldTokens;
// (gas) Promoted to compile-time constants so every hot-path read becomes
// a PUSH instead of an SLOAD. Safe because TokenTax is non-upgradeable and
// freshly deployed per createToken — storage layout of live tokens is
// unaffected (they keep the old slots baked into their own bytecode).
uint256 internal constant PRECISION = 10 ** 28;
uint256 internal reflectionsPerShareAmount;
uint256 internal wethYieldBalance;
address internal constant helpers = 0xd3397b405A2272F5C27fc673BE20579f22f59D6C;
address internal constant wethAddress = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27; // WPLS on PulseChain
mapping(address => uint256) internal reflectionDebt;
mapping(address => bool) public isReflectionExcluded;
mapping(address => mapping(address => UserYield)) internal userYields;
mapping(address => uint256[]) internal yieldTokenReflectionDebts;
bool internal inSwap;
modifier lockSwap() {
inSwap = true;
_;
inSwap = false;
}
// (gas) Former assignments moved to constant declarations above.
constructor() {}
// ------------------------------------------ REFLECTIONS -------------------------------------------------//
function getCurrentReflectionsPerShareAmount()
external
view
returns (uint256)
{
return reflectionsPerShareAmount;
}
function isExcludedFromReflections(
address account
) public view returns (bool) {
return isReflectionExcluded[account];
}
function pendingReflections(address account) public view returns (uint256) {
if (isExcludedFromReflections(account)) {
return 0;
}
return cleanPendingReflections(account);
}
function cleanPendingReflections(
address account
) internal view returns (uint256) {
return
Helpers(helpers).cleanPendingReflections(
account,
address(this),
reflectionsPerShareAmount,
reflectionDebt[account],
PRECISION
);
}
function updateAndClaimReflections(
address from,
address to,
address deployer
)
internal
returns (uint256 fromAmount, uint256 toAmount, uint256 deployerAmount)
{
if (from == to) {
fromAmount = isExcludedFromReflections(from)
? 0
: pendingReflections(from);
toAmount = 0; // Set to zero to avoid double claiming
} else {
fromAmount = isExcludedFromReflections(from)
? 0
: pendingReflections(from);
toAmount = isExcludedFromReflections(to)
? 0
: pendingReflections(to);
}
deployerAmount = cleanPendingReflections(deployer);
reflectionDebt[deployer] = reflectionsPerShareAmount;
reflectionDebt[from] = reflectionsPerShareAmount;
reflectionDebt[to] = reflectionsPerShareAmount;
}
// function tokenPendingReflections() public view returns (uint256) {
// uint256 currentBalance = IERC20(address(this)).balanceOf(address(this));
// uint256 newReflectionDebt = reflectionsPerShareAmount;
// if (newReflectionDebt <= reflectionDebt[address(this)]) {
// return 0;
// }
// return (newReflectionDebt - reflectionDebt[address(this)]) * currentBalance / PRECISION;
// }
// ------------------------------------------ YIELD TOKENS REFLECTIONS -------------------------------------------------//
function addYieldToken(
address tokenAddress
) internal returns (uint256 tokenIndex) {
for (uint256 i = 0; i < yieldTokens.length; i++) {
if (yieldTokens[i].tokenAddress == tokenAddress) {
return i;
}
}
yieldTokens.push(
YieldToken({
tokenAddress: tokenAddress,
reflectionsPerShareAmount: 0
})
);
return yieldTokens.length - 1;
}
function pendingYields(
address account,
uint256 tokenIndex
) public view returns (uint256) {
if (tokenIndex >= yieldTokenReflectionDebts[account].length) {
return 0;
}
return
Helpers(helpers).pendingYields(
account,
address(this),
yieldTokens[tokenIndex].reflectionsPerShareAmount,
yieldTokenReflectionDebts[account][tokenIndex],
PRECISION
);
}
function updateAndClaimYield(
address from,
address to,
address deployer
) internal {
for (uint256 i = 0; i < yieldTokens.length; i++) {
while (yieldTokenReflectionDebts[from].length <= i) {
yieldTokenReflectionDebts[from].push(
yieldTokens[i].reflectionsPerShareAmount
);
}
while (yieldTokenReflectionDebts[to].length <= i) {
yieldTokenReflectionDebts[to].push(
yieldTokens[i].reflectionsPerShareAmount
);
}
while (yieldTokenReflectionDebts[deployer].length <= i) {
yieldTokenReflectionDebts[deployer].push(
yieldTokens[i].reflectionsPerShareAmount
);
}
uint256 fromAmount = isExcludedFromReflections(from)
? 0
: pendingYields(from, i);
uint256 toAmount = 0; // Initialize to 0
if (from != to) {
toAmount = isExcludedFromReflections(to)
? 0
: pendingYields(to, i);
}
uint256[] memory transferAmounts = new uint256[](2);
address[] memory recipients = new address[](2);
uint256 recipientCount = 0;
if (fromAmount > 0) {
transferAmounts[recipientCount] = fromAmount;
recipients[recipientCount] = from;
recipientCount++;
}
if (toAmount > 0) {
transferAmounts[recipientCount] = toAmount;
recipients[recipientCount] = to;
recipientCount++;
}
for (uint256 j = 0; j < recipientCount; j++) {
if (transferAmounts[j] > 0) {
try
IERC20(yieldTokens[i].tokenAddress).transfer(
recipients[j],
transferAmounts[j]
)
{
if (yieldTokens[i].tokenAddress == wethAddress) {
wethYieldBalance -= transferAmounts[j];
}
yieldTokenReflectionDebts[recipients[j]][
i
] = yieldTokens[i].reflectionsPerShareAmount;
} catch {}
}
}
}
}
function getYieldTokens() public view returns (YieldToken[] memory) {
return yieldTokens;
}
function getYieldTokenReflectionDebts(
address account
) public view returns (uint256[] memory) {
return yieldTokenReflectionDebts[account];
}
}
// contracts/Tokens/ERC20.sol
// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/ERC20.sol)
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256))
private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(
address owner,
address spender
) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(
address spender,
uint256 value
) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(
address from,
address to,
uint256 value
) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(
address from,
address to,
uint256 value
) internal virtual {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(
address owner,
address spender,
uint256 value,
bool emitEvent
) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 value
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(
spender,
currentAllowance,
value
);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}
// contracts/Tokens/SmartTrader.sol
contract SmartTrader is Ownable {
constructor() Ownable(msg.sender) {}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
address _router,
address _receiver,
uint256 amountIn,
address[] memory path
) public {
IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn);
IERC20(path[0]).approve(_router, amountIn);
IUniswapV2Router02(_router)
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn,
0,
path,
address(this),
block.timestamp
);
uint256 receivedAmount = IERC20(path[path.length - 1]).balanceOf(
address(this)
);
IERC20(path[path.length - 1]).transfer(_receiver, receivedAmount);
}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
address _router,
address _receiver,
uint256 amountIn,
address[] calldata path
) public {
IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn);
IERC20(path[0]).approve(_router, amountIn);
IUniswapV2Router02(_router)
.swapExactTokensForETHSupportingFeeOnTransferTokens(
amountIn,
0,
path,
_receiver,
block.timestamp
);
payable(_receiver).transfer(address(this).balance);
}
function buyToken(
address _router,
address _receiver,
uint256 amountIn,
address[] memory path
) public {
IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn);
IERC20(path[0]).approve(_router, amountIn);
IUniswapV2Router02(_router)
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn,
0,
path,
_receiver,
block.timestamp
);
}
function addLiquidity(
address _router,
address tokenA,
address tokenB,
uint256 amountA,
uint256 amountB,
address lpReceiver
) public {
IERC20(tokenA).transferFrom(msg.sender, address(this), amountA);
IERC20(tokenB).transferFrom(msg.sender, address(this), amountB);
IERC20(tokenA).approve(_router, amountA);
IERC20(tokenB).approve(_router, amountB);
IUniswapV2Router02(_router).addLiquidity(
tokenA, tokenB, amountA, amountB, 0, 0, lpReceiver, block.timestamp
);
// Return any dust
uint256 dustA = IERC20(tokenA).balanceOf(address(this));
if (dustA > 0) IERC20(tokenA).transfer(msg.sender, dustA);
uint256 dustB = IERC20(tokenB).balanceOf(address(this));
if (dustB > 0) IERC20(tokenB).transfer(msg.sender, dustB);
}
function withdrawPLS() external onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "No PLS to withdraw");
payable(owner()).transfer(balance);
}
function withdrawToken(address tokenAddress) external onlyOwner {
IERC20 token = IERC20(tokenAddress);
uint256 balance = token.balanceOf(address(this));
require(balance > 0, "No tokens to withdraw");
token.transfer(owner(), balance);
}
receive() external payable {}
}
interface IWETH_1 {
function withdraw(uint256 wad) external;
}
contract TokenTax is ERC20, Ownable, Manager {
//
// ███╗ ██╗███████╗██╗ ██╗██╗ ██████╗ ███╗ ██╗
// ████╗ ██║██╔════╝╚██╗██╔╝██║██╔═══██╗████╗ ██║
// ██╔██╗ ██║█████╗ ╚███╔╝ ██║██║ ██║██╔██╗ ██║
// ██║╚██╗██║██╔══╝ ██╔██╗ ██║██║ ██║██║╚██╗██║
// ██║ ╚████║███████╗██╔╝ ██╗██║╚██████╔╝██║ ╚████║
// ╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝
//
// * . * * . * . *
// . * * . . *
// . * .
// . * * * . * . *
// _____ _____
// .| |. * . * .| |.
// || || . *|| ||
// || ___ || * . || ___ ||
// * |:_____:| * |:_____:|
// |_______| . * * |_______|. *
// . | . . | . | . . |
// | . . | * . | . . | *
// '._____.'. * * .'._____.'.
//
// Revolutionary Hyper-Deflationary and Bonded Liquidity Ecosystem
//
// Telegram: https://t.me/NexionPulse
// Website: https://nexionpulse.com/
// X: https://x.com/nexionpulse
// Contract: 0xF2Da3942616880E52e841E5C504B5A9Fba23FFF0
//
uint256 public initialSupply;
bool public tradingEnabled;
uint64 public enableTradingAt; // timestamp for auto-enable (0 = manual only)
error TradingDisabled();
error AlreadyEnabled();
event TradingEnabled();
address payable private smartTrader;
address private deployer;
address private factory;
address[] private routers = [
0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02,
0x165C3410fC91EF562C50559f7d2289fEbed552d9,
0xcC73b59F8D7b7c532703bDfea2808a28a488cF47,
0xeB45a3c4aedd0F47F345fB4c8A1802BB5740d725
];
mapping(address => bool) isTaxExcluded;
/// @dev (G2) Deprecated storage slot — must remain to preserve UUPS layout.
/// Previously written on every taxed transfer; now passed as a function
/// parameter through processAccumulatedTaxes / Helpers.getProcessingAmount.
/// Reads still happen via the legacy internal getProcessingAmount(uint256)
/// helper below, but no on-path code writes to this slot anymore.
uint256 private __deprecated_currentSwapAmount;
uint256 private accumulatedFee;
// Parallel platform-style bucket for the Neon LP autoBuy/autoLP feed.
// Funded the same way as `accumulatedFee` (bps of each user tax) but
// routed to NEON_LP_RECEIVER instead of getWallet() during processAccumulatedTaxes.
// Never cannibalises the creator's tax bucket.
uint256 private accumulatedNeonFee;
bool private shouldAccumulateFee;
bool private reflectionsEnabled;
bool private yieldEnabled;
bool private firstPairInteractionHappened;
bool private processedTaxesInTx;
// Add all the events for tax tracking
event TaxCollected(
uint256 indexed taxId,
Helpers.TaxType taxType,
Helpers.TaxMoment taxMoment,
address from,
address to,
uint256 amount,
uint256 timestamp
);
event noRouter();
event BurnTaxProcessed(uint256 amount, uint256 timestamp);
event ExternalBurnProcessed(
uint256 tokenAmount,
uint256 taxid,
uint256 wethAmount,
address receiver,
address tokenToBurn,
uint256 timestamp
);
event ReflectionTaxProcessed(
uint256 amount,
uint256 newReflectionsPerShareAmount,
uint256 timestamp
);
event ReflectionDistributed(
address from,
address to,
uint256 fromAmount,
uint256 toAmount,
uint256 deployerAmount,
uint256 reflectionsPerShareAmount,
uint256 timestamp
);
event YieldTaxProcessed(
uint256 tokenAmount,
uint256 wethAmount,
address yieldTokenAddress,
uint256 timestamp
);
event YieldDistributed(
address tokenAddress,
address recipient,
uint256 amount,
uint256 reflectionsPerShareAmount,
uint256 timestamp
);
Helpers.Tax[] public taxes;
error ZeroTaxPercentage();
uint256 public totalBurned; // Track burn taxes
uint256 public totalSupport; // Track external burn taxes
uint256 public totalReflection; // Track reflection taxes
uint256 public totalYield; // Track yield taxes
uint256 public totalLiquify; // Track liquify taxes
address internal constant deadAddress = 0x000000000000000000000000000000000000dEaD;
constructor(
DeployTokenParams memory p
) ERC20(p.name_, p.symbol_) Ownable(p.owner_) Manager() {
tradingEnabled = p.tradingEnabled;
enableTradingAt = p.enableTradingAt;
_mint(p.mintTo, p.initialSupply);
// Burn on deploy: real _burn that reduces totalSupply
if (p.burnOnDeployPct > 0) {
uint256 burnAmount = (p.initialSupply * p.burnOnDeployPct) / 10000;
_burn(p.mintTo, burnAmount);
}
// Transfer vested tokens to vesting contract
if (p.vestAmount > 0 && p.vestingContract != address(0)) {
super._transfer(p.mintTo, p.vestingContract, p.vestAmount);
}
deployer = p.mintTo;
initialSupply = p.initialSupply;
smartTrader = payable(p.smartTrader);
factory = p.factory;
// Inline taxesInitialize (can't rely on deployed Helpers for Liquify enum)
// (G4) Zero-percentage check now lives inside _initializeTaxes; the
// duplicate post-loop has been removed.
_initializeTaxes(p.taxes);
inititlizeTaxExclusions();
if (reflectionsEnabled || yieldEnabled)
initializeReflectionExclusions();
IERC20(wethAddress).approve(smartTrader, 2 ** 256 - 1);
_approve(address(this), smartTrader, 2 ** 256 - 1);
}
function _initializeTaxes(Helpers.Tax[] memory _taxes) internal {
uint256 totalTaxPct;
for (uint256 i; i < _taxes.length; i++) {
taxes.push(_taxes[i]);
taxes[i].id = i;
// (G4) Hoisted from the second constructor loop
if (_taxes[i].percentage == 0) revert ZeroTaxPercentage();
require(_taxes[i].percentage <= 5000, "Tax percentage too high");
if (_taxes[i].taxMoment == Helpers.TaxMoment.Both) {
totalTaxPct += _taxes[i].percentage * 2;
} else {
totalTaxPct += _taxes[i].percentage;
}
if (_taxes[i].taxType == Helpers.TaxType.Reflection) {
reflectionsEnabled = true;
}
if (_taxes[i].taxType == Helpers.TaxType.Yield) {
yieldEnabled = true;
if (_taxes[i].tokenAddress != address(0)) {
addYieldToken(_taxes[i].tokenAddress);
}
}
if (_taxes[i].taxType == Helpers.TaxType.ExternalBurn) {
require(_taxes[i].receiver != address(0), "ExternalBurn: receiver cannot be zero");
require(_taxes[i].tokenAddress != address(0), "ExternalBurn: tokenAddress cannot be zero");
shouldAccumulateFee = true;
} else if (_taxes[i].taxType == Helpers.TaxType.Dev) {
require(_taxes[i].receiver != address(0), "Dev: receiver cannot be zero");
if (_taxes[i].rewardInPls) {
shouldAccumulateFee = true;
}
} else if (_taxes[i].taxType == Helpers.TaxType.Yield) {
require(_taxes[i].tokenAddress != address(0), "Yield: tokenAddress cannot be zero");
shouldAccumulateFee = true;
} else if (_taxes[i].taxType == Helpers.TaxType.Liquify) {
shouldAccumulateFee = true;
}
}
require(totalTaxPct <= 8000, "Total tax percentage too high");
}
function _transfer(
address from,
address to,
uint256 value
) internal override {
processedTaxesInTx = false;
// (gas #7) Cache `tradingEnabled` and `isTaxExcluded[from]` once —
// both are touched multiple times below, and caching saves 2 SLOADs
// per transfer on the common taxed path.
bool _trading = tradingEnabled;
bool _fromExcluded = isTaxExcluded[from];
// Auto-enable trading if timer has passed
if (!_trading && enableTradingAt > 0 && block.timestamp >= enableTradingAt) {
tradingEnabled = true;
_trading = true;
emit TradingEnabled();
}
if (isDeadAddress(to)) {
super._burn(from, value);
return;
}
// Block non-excluded transfers when trading is disabled
if (!_trading && !_fromExcluded) revert TradingDisabled();
bool _isPairTo = isPair(to);
if (
taxes.length == 0 ||
!firstPairInteractionHappened ||
_fromExcluded ||
isTaxExcluded[to] ||
inSwap
) {
if (!firstPairInteractionHappened && _isPairTo)
firstPairInteractionHappened = true;
_claimYield(from, to);
super._transfer(from, to, value);
return;
}
if (_isPairTo && !isReflectionExcluded[to])
isReflectionExcluded[to] = true;
// (gas #3A) Compute isBuy/isSell ONCE here and thread them through
// processTaxes + the post-tax gating block. Prior code called
// Helpers.isBuy twice per taxed transfer (once inside processTaxes,
// once after). Now it's a single STATICCALL, with isSell only
// evaluated when isBuy is false (preserves the G3 short-circuit).
bool _isBuy = isBuy(from, to);
bool _isSell = _isBuy ? false : isSell(from, to);
// (G2) `value` is plumbed directly through processAccumulatedTaxes
// instead of via the deprecated currentSwapAmount storage slot.
uint256 amountAfterTaxs = processTaxes(from, to, value, _isBuy, _isSell);
// (gas #6) `hasAccumulatedTaxes()` was provably dead: it only returned
// true when some tax.amountAccumulated > 0, and amountAccumulated is
// only written by the four processors (ExternalBurn / Yield / Liquify
// / Dev+rewardInPls) that set `shouldAccumulateFee = true` in the
// constructor. `firstPairInteractionHappened` and `!inSwap` are also
// already guaranteed by the early-return guard above. Collapsed to a
// single boolean check.
if (shouldAccumulateFee && !processedTaxesInTx && !_isBuy) {
processAccumulatedTaxes(value);
processedTaxesInTx = true;
}
_claimYield(from, to);
_claimReflections(from, to);
super._transfer(from, to, amountAfterTaxs);
}
/// @dev Bundle of loop-invariant context for _processOneTaxLeg. Passed
/// as a single memory struct to keep the per-call argument count
/// under the non-via-ir stack-too-deep ceiling.
struct TaxLegCtx {
address from;
address to;
uint256 amount;
bool isBuy;
bool isSell;
uint256 neonFeeBps;
uint256 fee;
}
function processTaxes(
address from,
address to,
uint256 amount,
bool _isBuy,
bool _isSell
) internal returns (uint256) {
uint256 totalTaxAmount;
uint256 totalFee;
uint256 totalNeonFee;
TaxLegCtx memory ctx;
ctx.from = from;
ctx.to = to;
ctx.amount = amount;
// (gas #3A) isBuy/isSell are now computed once by the caller and
// passed in, eliminating a duplicate Helpers.isBuy STATICCALL.
// The G3 short-circuit is preserved at the caller.
ctx.isBuy = _isBuy;
ctx.isSell = _isSell;
// Parallel Neon LP fee, taken in bps of each user-tax slice (NOT volume,
// NOT from the platform Fee bucket, NOT from creator's leftover WPLS).
// Only fires when shouldAccumulateFee is true — i.e. the token has a
// tax type that requires the WPLS swap pipeline. Otherwise the neon
// tokens would have no path out and would just sit in the contract.
if (shouldAccumulateFee && getNeonLpReceiver() != address(0)) {
ctx.neonFeeBps = getNeonLpFee();
}
// (G1) Read the platform FEE once per transfer instead of once per
// tax leg. Saves N-1 STATICCALLs to the factory per taxed trade.
// (#4) Cache the taxes array to memory once. processTaxes only reads
// immutable fields (taxType/taxMoment/percentage/receiver/etc.);
// writes to amountAccumulated still go through storage in
// processTaxType via taxes[tax.id], so accounting is unaffected.
ctx.fee = getFee();
Helpers.Tax[] memory _cachedTaxes = taxes;
uint256 len = _cachedTaxes.length;
for (uint256 i; i < len; i++) {
(uint256 _taxAmount, uint256 _Fee, uint256 _neonFee) = _processOneTaxLeg(
ctx, _cachedTaxes[i]
);
totalTaxAmount += _taxAmount;
totalFee += _Fee;
totalNeonFee += _neonFee;
}
if (totalFee > 0) {
if (shouldAccumulateFee) {
super._transfer(from, address(this), totalFee);
accumulatedFee += totalFee;
} else {
super._transfer(from, getWallet(), totalFee);
}
}
if (totalNeonFee > 0) {
// Neon fee always accumulates for the swap pipeline (gated above
// on shouldAccumulateFee, so we know the swap path will run).
super._transfer(from, address(this), totalNeonFee);
accumulatedNeonFee += totalNeonFee;
}
return amount - totalTaxAmount - totalFee - totalNeonFee;
}
/// @dev Per-tax-leg helper extracted from processTaxes() to keep that
/// frame under the stack-too-deep limit. Computes the user-tax /
/// dev-fee / neon-fee triple, routes the user-tax portion to its
/// destination, and returns the three amounts so the caller can
/// accumulate totals. Loop-invariant context (from/to/amount/
/// isBuy/isSell/neonFeeBps/fee) is bundled into TaxLegCtx to keep
/// the argument count below the non-via-ir stack ceiling.
function _processOneTaxLeg(
TaxLegCtx memory ctx,
Helpers.Tax memory tax
) internal returns (uint256 taxAmount, uint256 Fee, uint256 neonFee) {
bool fired;
if (tax.taxMoment == Helpers.TaxMoment.Both) {
(taxAmount, Fee) = calculateTaxAmount(ctx.amount, tax, ctx.fee);
fired = true;
} else if (tax.taxMoment == Helpers.TaxMoment.Buy && ctx.isBuy) {
(taxAmount, Fee) = calculateTaxAmount(ctx.amount, tax, ctx.fee);
fired = true;
} else if (tax.taxMoment == Helpers.TaxMoment.Sell && ctx.isSell) {
(taxAmount, Fee) = calculateTaxAmount(ctx.amount, tax, ctx.fee);
fired = true;
}
if (!fired) return (0, 0, 0);
// Slice neon out of the user-tax portion (NOT out of dev Fee).
if (ctx.neonFeeBps > 0 && taxAmount > 0) {
neonFee = (taxAmount * ctx.neonFeeBps) / 10000;
taxAmount -= neonFee;
}
processTaxType(ctx.from, ctx.to, taxAmount, tax);
}
/// @dev (G1) Now takes the cached platform fee as a parameter rather than
/// reading it via an external call to the factory on every call.
function calculateTaxAmount(
uint256 originalAmount,
Helpers.Tax memory tax,
uint256 fee_
) internal view returns (uint256 taxAmount, uint256 Fee) {
return
Helpers(helpers).calculateTaxAmount(
originalAmount,
tax.percentage,
fee_,
true,
10000
);
}
/// @param to (#2) Real transfer recipient — used as the TaxCollected.to
/// field instead of msg.sender. Off-chain indexers reading the
/// previous (broken) field were always seeing the router on
/// swaps. New deployments emit the correct counterparty.
function processTaxType(
address from,
address to,
uint256 taxAmount,
Helpers.Tax memory tax
) internal {
// Emit tax collection event for all types
emit TaxCollected(
tax.id,
tax.taxType,
tax.taxMoment,
from,
to,
taxAmount,
block.timestamp
);
if (tax.taxType == Helpers.TaxType.Burn) {
processBurnTax(from, taxAmount);
} else if (tax.taxType == Helpers.TaxType.Reflection) {
processReflectionTax(from, taxAmount);
} else if (tax.taxType == Helpers.TaxType.Dev) {
processTreasuryTax(from, taxAmount, tax);
} else if (tax.taxType == Helpers.TaxType.ExternalBurn) {
processSupportTax(from, taxAmount, tax);
} else if (tax.taxType == Helpers.TaxType.Yield) {
processYieldTax(from, taxAmount, tax);
} else if (tax.taxType == Helpers.TaxType.Liquify) {
processLiquifyTax(from, taxAmount, tax);
}
}
function burn(uint256 amount) public {
totalBurned += amount;
emit BurnTaxProcessed(amount, block.timestamp);
super._burn(msg.sender, amount);
}
function processBurnTax(address from, uint256 taxAmount) internal {
totalBurned += taxAmount;
emit BurnTaxProcessed(taxAmount, block.timestamp);
super._burn(from, taxAmount);
}
function processTreasuryTax(
address from,
uint256 taxAmount,
Helpers.Tax memory tax
) internal {
if (!isTaxExcluded[tax.receiver]) isTaxExcluded[tax.receiver] = true;
if (tax.rewardInPls) {
super._transfer(from, address(this), taxAmount);
taxes[tax.id].amountAccumulated += taxAmount;
} else {
super._transfer(from, tax.receiver, taxAmount);
}
}
function processReflectionTax(address from, uint256 taxAmount) internal {
super._transfer(from, address(this), taxAmount);
uint256 supply = totalSupply() - balanceOf(address(this));
if (supply > 0) {
reflectionsPerShareAmount += (taxAmount * PRECISION) / supply;
totalReflection += taxAmount;
}
emit ReflectionTaxProcessed(
taxAmount,
reflectionsPerShareAmount,
block.timestamp
);
}
function processSupportTax(
address from,
uint256 taxAmount,
Helpers.Tax memory tax
) internal lockSwap {
super._transfer(from, address(this), taxAmount);
taxes[tax.id].amountAccumulated += taxAmount;
totalSupport += taxAmount;
emit ExternalBurnProcessed(
taxAmount,
tax.id,
0,
tax.receiver,
tax.tokenAddress,
block.timestamp
);
}
function processYieldTax(
address from,
uint256 taxAmount,
Helpers.Tax memory tax
) internal lockSwap {
super._transfer(from, address(this), taxAmount);
taxes[tax.id].amountAccumulated += taxAmount;
totalYield += taxAmount;
emit YieldTaxProcessed(
taxAmount,
0, // wethAmount (will be updated when processed)
tax.tokenAddress,
block.timestamp
);
}
function processLiquifyTax(
address from,
uint256 taxAmount,
Helpers.Tax memory tax
) internal lockSwap {
super._transfer(from, address(this), taxAmount);
taxes[tax.id].amountAccumulated += taxAmount;
totalLiquify += taxAmount;
}
function processAccumulatedTaxes(uint256 swapAmount) internal lockSwap {
uint256 totalToSwap = 0;
uint256 totalTokenTypes = 0;
uint256 tl = taxes.length;
bool[] memory taxesToProcess = new bool[](tl);
uint256[] memory taxAmounts = new uint256[](tl);
for (uint256 i; i < tl; i++) {
Helpers.Tax storage tax = taxes[i];
if (tax.amountAccumulated == 0) continue;
if (
tax.taxType == Helpers.TaxType.ExternalBurn ||
(tax.taxType == Helpers.TaxType.Dev && tax.rewardInPls) ||
tax.taxType == Helpers.TaxType.Yield ||
tax.taxType == Helpers.TaxType.Liquify
) {
(uint256 swapAmount, uint256 _newAccumulatedAmount) = Helpers(
helpers
).getProcessingAmount(tax.amountAccumulated, swapAmount);
if (swapAmount > 0) {
uint256 amountToSwap = swapAmount;
uint256 finalAccumulatedAmount = _newAccumulatedAmount;
// For Liquify, only swap half — keep other half for liquidity
if (tax.taxType == Helpers.TaxType.Liquify) {
amountToSwap = swapAmount / 2;
finalAccumulatedAmount = _newAccumulatedAmount + (swapAmount - amountToSwap);
}
taxesToProcess[i] = true;
taxAmounts[i] = amountToSwap;
totalToSwap += amountToSwap;
totalTokenTypes++;
taxes[i].amountAccumulated = finalAccumulatedAmount;
} else {
taxes[i].amountAccumulated = _newAccumulatedAmount;
}
}
}
(, /*address bestPair*/ address bestRouter) = Helpers(helpers)
.getBestPair(address(this), wethAddress, routers);
if (bestRouter == address(0)) {
emit noRouter();
return;
}
// Pull both platform buckets from storage. Scoped block so the
// `newAcc*` temporaries don't pollute the outer stack frame.
uint256 ToProcess;
uint256 NeonToProcess;
{
uint256 newAcc;
uint256 newAccNeon;
(ToProcess, newAcc) = Helpers(helpers).getProcessingAmount(
accumulatedFee, swapAmount
);
(NeonToProcess, newAccNeon) = Helpers(helpers).getProcessingAmount(
accumulatedNeonFee, swapAmount
);
accumulatedFee = newAcc;
accumulatedNeonFee = newAccNeon;
}
totalToSwap += ToProcess;
totalToSwap += NeonToProcess;
if (totalToSwap == 0) return;
// _approve(address(this), smartTrader, totalToSwap);
try
SmartTrader(smartTrader)
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
bestRouter,
address(this),
totalToSwap,
getTokenWETHPath(address(this))
)
{} catch {
for (uint256 i; i < tl; i++) {
if (taxesToProcess[i]) {
taxes[i].amountAccumulated += taxAmounts[i];
}
}
accumulatedFee += ToProcess;
accumulatedNeonFee += NeonToProcess;
return;
}
uint256 totalWethReceived = IERC20(wethAddress).balanceOf(
address(this)
) - wethYieldBalance;
// Pay dev wallet (FEE bps slice) + Neon LP receiver (NEON_LP_FEE bps
// parallel slice) and shrink the WPLS pool down to the creator's share.
// Helper extracted to keep this frame under the stack-too-deep limit.
totalWethReceived -= _distributeFeesAndNeon(
totalWethReceived, ToProcess, NeonToProcess, totalToSwap
);
totalToSwap -= ToProcess;
totalToSwap -= NeonToProcess;
if (totalWethReceived == 0) return;
for (uint256 i; i < tl; i++) {
if (!taxesToProcess[i] || taxAmounts[i] == 0) continue;
uint256 wethPortion = (taxAmounts[i] * totalWethReceived) /
totalToSwap;
Helpers.Tax storage tax = taxes[i];
if (tax.taxType == Helpers.TaxType.ExternalBurn) {
emit ExternalBurnProcessed(
taxAmounts[i],
tax.id,
wethPortion,
tax.receiver,
tax.tokenAddress,
block.timestamp
);
processExternalBurnWeth(wethPortion, tax);
} else if (tax.taxType == Helpers.TaxType.Dev && tax.rewardInPls) {
sendWETH(wethPortion, tax.receiver);
} else if (tax.taxType == Helpers.TaxType.Yield) {
emit YieldTaxProcessed(
taxAmounts[i],
wethPortion,
tax.tokenAddress,
block.timestamp
);
processYieldWeth(wethPortion, tax);
} else if (tax.taxType == Helpers.TaxType.Liquify) {
processLiquifyWeth(wethPortion, tax);
}
}
}
/// @dev Pays the dev wallet share + the Neon LP share out of the just-swapped
/// WPLS pool. Returns total WPLS spent so the caller can shrink its pool.
/// Extracted from processAccumulatedTaxes() to keep that frame under the
/// stack-too-deep limit (we cannot use --via-ir per project rules).
function _distributeFeesAndNeon(
uint256 totalWethReceived,
uint256 toProcess,
uint256 neonToProcess,
uint256 totalToSwap_
) internal returns (uint256 spent) {
// Dev wallet — unchanged behaviour, full FEE bps cut.
uint256 devSlice = (totalWethReceived * toProcess) / totalToSwap_;
if (devSlice > 0) sendWETH(devSlice, getWallet());
// Neon LP — parallel cut. Receiver is read at distribution time so a
// mid-flight setNeonLpReceiver() always routes pending neon to the
// latest configured contract. If receiver is unset, the corresponding
// WPLS is left on the token (rescuable via rescueToken).
uint256 neonSlice = (totalWethReceived * neonToProcess) / totalToSwap_;
if (neonSlice > 0) {
address neonRecv = getNeonLpReceiver();
if (neonRecv != address(0)) sendWETH(neonSlice, neonRecv);
}
return devSlice + neonSlice;
}
function processExternalBurnWeth(
uint256 wethAmount,
Helpers.Tax memory tax
) internal {
if (wethAmount == 0) return;
if (tax.tokenAddress == wethAddress) {
IERC20(wethAddress).transfer(tax.receiver, wethAmount);
return;
}
(, /*address bestTargetPair*/ address bestTargetRouter) = Helpers(
helpers
).getBestPair(wethAddress, tax.tokenAddress, routers);
// IERC20(wethAddress).approve(smartTrader, 2**256-1);
try
SmartTrader(smartTrader).buyToken(
bestTargetRouter,
tax.receiver,
wethAmount,
getWETHBuyBurnPath(tax.tokenAddress)
)
{} catch {
IERC20(wethAddress).transfer(tax.receiver, wethAmount);
}
}
/// @dev KNOWN BUG (mitigated off-chain in the deployment UI):
/// On the success path of `withdraw`, the WPLS has already been
/// unwrapped to native PLS. If the subsequent `.call` fails (receiver
/// is a contract that rejects PLS — Safe with no `receive()`,
/// blacklist-bound contract, etc.), the fallback `transfer` of WETH
/// operates on a balance that no longer exists for this slice.
/// Two failure modes:
/// 1. Hard revert if the contract holds no other WETH → bricks
/// every subsequent user transfer (processAccumulatedTaxes runs
/// inside _transfer with no try/catch wrapping it).
/// 2. Silent dip into `wethYieldBalance` if yield reserves exist →
/// the next processAccumulatedTaxes computes
/// `weth.balanceOf(this) - wethYieldBalance` and underflows
/// (panic), permanently bricking tax processing for this token.
/// Trigger surfaces the UI cannot fully cover:
/// (a) factory `WALLET` (set by factory owner via setWallet)
/// (b) `NEON_LP_RECEIVER` (set by factory owner via setNeonLpReceiver)
/// (c) any receiver contract that becomes PLS-rejecting AFTER
/// deployment (multisig reconfig, paused flag, etc.)
/// The deployment UI validates per-token dev receivers can accept
/// PLS at create time, which mitigates the most common surface
/// (the dev receiver picked at create) but does NOT cover (a)/(b)/(c).
/// Long-term fix: re-wrap PLS via `IWETH(wethAddress).deposit{value: wethAmount}()`
/// before the fallback transfer, OR never unwrap and always send WETH.
function sendWETH(uint256 wethAmount, address receiver) internal {
if (wethAmount == 0) return;
try IWETH_1(wethAddress).withdraw(wethAmount) {
(bool success, ) = receiver.call{value: wethAmount}("");
if (!success) {
IERC20(wethAddress).transfer(receiver, wethAmount);
} else {}
} catch {
IERC20(wethAddress).transfer(receiver, wethAmount);
}
}
function processYieldWeth(
uint256 wethAmount,
Helpers.Tax memory tax
) internal {
if (wethAmount == 0) return;
if (tax.tokenAddress == wethAddress) {
wethYieldBalance += wethAmount;
uint256 tokenIndex = addYieldToken(tax.tokenAddress);
uint256 supply = totalSupply() - balanceOf(address(this));
if (supply > 0) {
yieldTokens[tokenIndex].reflectionsPerShareAmount +=
(wethAmount * PRECISION) /
supply;
emit YieldDistributed(
tax.tokenAddress,
address(this),
wethAmount,
yieldTokens[tokenIndex].reflectionsPerShareAmount,
block.timestamp
);
}
return;
}
(, /*address bestTargetPair*/ address bestTargetRouter) = Helpers(
helpers
).getBestPair(wethAddress, tax.tokenAddress, routers);
uint256 initialTokenBalance = IERC20(tax.tokenAddress).balanceOf(
address(this)
);
// IERC20(wethAddress).approve(smartTrader, wethAmount);
try
SmartTrader(smartTrader).buyToken(
bestTargetRouter,
address(this),
wethAmount,
getWETHBuyBurnPath(tax.tokenAddress)
)
{
uint256 finalTokenBalance = IERC20(tax.tokenAddress).balanceOf(
address(this)
);
uint256 boughtAmount = finalTokenBalance - initialTokenBalance;
if (boughtAmount > 0) {
uint256 tokenIndex = addYieldToken(tax.tokenAddress);
uint256 supply = totalSupply() - balanceOf(address(this));
if (supply > 0) {
yieldTokens[tokenIndex].reflectionsPerShareAmount +=
(boughtAmount * PRECISION) /
supply;
emit YieldDistributed(
tax.tokenAddress,
address(this),
boughtAmount,
yieldTokens[tokenIndex].reflectionsPerShareAmount,
block.timestamp
);
}
}
} catch {}
}
function processLiquifyWeth(
uint256 wethAmount,
Helpers.Tax storage tax
) internal {
if (wethAmount == 0) return;
// Use the tokens that were kept in the contract for liquidity
uint256 tokensForLiquidity = tax.amountAccumulated;
if (tokensForLiquidity == 0) return;
// Determine pair token: WPLS (default) or custom token from tax.tokenAddress
address pairToken = tax.tokenAddress;
bool useCustomPairToken = pairToken != address(0) && pairToken != wethAddress;
uint256 pairTokenAmount = wethAmount;
if (useCustomPairToken) {
// Swap WPLS to the custom pair token first
(, address swapRouter) = Helpers(helpers).getBestPair(
wethAddress, pairToken, routers
);
if (swapRouter == address(0)) return;
uint256 initialBalance = IERC20(pairToken).balanceOf(address(this));
IERC20(wethAddress).approve(smartTrader, wethAmount);
address[] memory path = new address[](2);
path[0] = wethAddress;
path[1] = pairToken;
try SmartTrader(smartTrader).swapExactTokensForTokensSupportingFeeOnTransferTokens(
swapRouter, address(this), wethAmount, path
) {
pairTokenAmount = IERC20(pairToken).balanceOf(address(this)) - initialBalance;
} catch {
// Swap failed, keep tokens for next cycle
return;
}
}
// Find best router for TOKEN/pairToken (or TOKEN/WPLS) pair
address lpPairToken = useCustomPairToken ? pairToken : wethAddress;
(, address bestRouter) = Helpers(helpers).getBestPair(
address(this), lpPairToken, routers
);
if (bestRouter == address(0)) return;
// Approve tokens for SmartTrader
// NOTE: must use type(uint256).max here, NOT tokensForLiquidity. SmartTrader.addLiquidity()
// calls transferFrom(this, helper, tokensForLiquidity) which would otherwise drain the
// allowance to zero, bricking every subsequent processAccumulatedTaxes() call (which
// relies on the constructor's max approval set at line 1763).
_approve(address(this), smartTrader, type(uint256).max);
// (gas #4A) When lpPairToken is WPLS (the common case), the
// constructor already granted smartTrader a max allowance on WPLS,
// so this per-cycle approve is a redundant ~5K-gas SSTORE. Only run
// it for the custom-pair-token path, where pairTokenAmount was just
// produced by the swap above and needs a fresh allowance.
if (useCustomPairToken) {
IERC20(lpPairToken).approve(smartTrader, pairTokenAmount);
}
try SmartTrader(smartTrader).addLiquidity(
bestRouter,
address(this),
lpPairToken,
tokensForLiquidity,
pairTokenAmount,
deadAddress // LP tokens burned = permanent liquidity
) {
taxes[tax.id].amountAccumulated = 0;
} catch {
// If adding liquidity fails, keep tokens for next cycle
}
}
function _claimReflections(address from, address to) internal {
if (!reflectionsEnabled) return;
(
uint256 fromAmount,
uint256 toAmount,
uint256 deployerAmount
) = updateAndClaimReflections(from, to, deployer);
emit ReflectionDistributed(
from,
to,
fromAmount,
toAmount,
deployerAmount,
reflectionsPerShareAmount,
block.timestamp
);
if (fromAmount != 0) {
if (!isPair(from)) {
super._transfer(address(this), from, fromAmount);
}
}
if (toAmount != 0) {
if (!isPair(to)) {
super._transfer(address(this), to, toAmount);
}
}
if (deployerAmount != 0) {
super._transfer(address(this), deployer, deployerAmount);
}
}
function initializeReflectionExclusions() internal {
isReflectionExcluded[address(0)] = true;
isReflectionExcluded[address(this)] = true;
for (uint256 i; i < routers.length; ) {
isReflectionExcluded[routers[i]] = true;
unchecked {
i++;
}
}
}
function isDeadAddress(address _address) internal pure returns (bool) {
return
_address == address(0) ||
_address == 0x0000000000000000000000000000000000000369 ||
_address == 0x000000000000000000000000000000000000dEaD;
}
function isPair(address _address) internal view returns (bool) {
return Helpers(helpers).isPair(_address, address(this));
}
function isBuy(address from, address to) internal view returns (bool) {
return Helpers(helpers).isBuy(from, to, address(this));
}
function isSell(address from, address to) internal view returns (bool) {
// Pair→pair (arb bot routing) is treated as a sell so the sell-tax fires.
if (isPair(from) && isPair(to)) return true;
return Helpers(helpers).isSell(from, to, address(this));
}
/// @dev (G2) Removed the internal `getProcessingAmount(uint256)` helper —
/// it was dead code and was the only remaining reader of the
/// deprecated `currentSwapAmount` storage slot. Active swap amounts
/// now flow through processAccumulatedTaxes(uint256 swapAmount).
function getTokenWETHPath(
address tokenAddress
) internal view returns (address[] memory) {
return Helpers(helpers).getTokenWPLSPath(tokenAddress);
}
function getWETHBuyBurnPath(
address tokenAddress
) internal view returns (address[] memory) {
return Helpers(helpers).getWPLSBuyBurnPath(tokenAddress);
}
function getTaxes() public view returns (Helpers.Tax[] memory) {
return taxes;
}
function getFee() public view returns (uint256) {
return ISmartTokenFactory(factory).FEE();
}
function getWallet() public view returns (address) {
return ISmartTokenFactory(factory).WALLET();
}
// (gas #8) Factory is the live TokenFactoryTax proxy whose ABI is pinned
// at token-deploy time, so these getters are guaranteed to exist. Drop
// the try/catch wrapper — saves ~200-500 gas per taxed transfer.
function getNeonLpFee() public view returns (uint256) {
return ISmartTokenFactory(factory).NEON_LP_FEE();
}
function getNeonLpReceiver() public view returns (address) {
return ISmartTokenFactory(factory).NEON_LP_RECEIVER();
}
function getaccumulatedFee() external view returns (uint256) {
return accumulatedFee;
}
function getaccumulatedNeonFee() external view returns (uint256) {
return accumulatedNeonFee;
}
function getTotalTaxs() external view returns (uint256) {
return Helpers(helpers).getTotalTaxs(taxes);
}
function forceProcessAccumulatedTaxes() external onlyOwner {
// (G2) Manual flush — pass max as the swap-budget so Helpers.getProcessingAmount
// does not artificially cap how much accumulated tax we drain.
processAccumulatedTaxes(type(uint256).max);
}
/// @notice Owner-only escape hatch: re-grant SmartTrader an unlimited
/// allowance over the token's self balance. The constructor sets
/// this to max already, so this is only needed if a future code
/// path drifts that allowance back down.
function reapproveSmartTrader() external onlyOwner {
_approve(address(this), smartTrader, type(uint256).max);
}
function enableTrading() external onlyOwner {
if (tradingEnabled) revert AlreadyEnabled();
tradingEnabled = true;
emit TradingEnabled();
}
function _claimYield(address from, address to) internal {
if (yieldEnabled) {
updateAndClaimYield(from, to, deployer);
}
}
function claimYield() external returns (bool) {
_claimYield(msg.sender, msg.sender);
return true;
}
function updateTaxReceiver(uint256 taxId, address newReceiver) external onlyOwner {
require(taxId < taxes.length, "Invalid tax ID");
require(newReceiver != address(0), "Receiver cannot be zero address");
taxes[taxId].receiver = newReceiver;
}
function updateTaxTokenAddress(uint256 taxId, address newTokenAddress) external onlyOwner {
require(taxId < taxes.length, "Invalid tax ID");
require(newTokenAddress != address(0), "Token address cannot be zero");
taxes[taxId].tokenAddress = newTokenAddress;
}
function addTaxExclusion(address _address) external onlyOwner {
isTaxExcluded[_address] = true;
}
function removeTaxExclusion(address _address) external onlyOwner {
isTaxExcluded[_address] = false;
}
function inititlizeTaxExclusions() internal {
isTaxExcluded[deployer] = true;
isTaxExcluded[address(this)] = true;
isTaxExcluded[smartTrader] = true;
isTaxExcluded[factory] = true;
//neon farms
isTaxExcluded[0x6dDcdfce43aC44F686464dB25dEc788F034a7fbb] = true;
isTaxExcluded[0x5dF85211Aa383994B03a52946B91329c25E622e9] = true;
// Airdrop contract — TODO: replace with deployed address
// isTaxExcluded[0x_AIRDROP_CONTRACT_ADDRESS_HERE] = true;
}
/// @notice Rescue stuck tokens — only factory owner can call
/// @dev For when users accidentally send tokens to the token contract
function rescueToken(address token, address to, uint256 amount) external {
require(msg.sender == Ownable(factory).owner(), "Only factory owner");
require(token != address(this), "Cannot rescue own token");
IERC20(token).transfer(to, amount);
}
/// @notice Rescue stuck PLS — only factory owner can call
function rescuePLS(address payable to, uint256 amount) external {
require(msg.sender == Ownable(factory).owner(), "Only factory owner");
(bool ok,) = to.call{value: amount}("");
require(ok, "Transfer failed");
}
receive() external payable {}
}
// contracts/Tokens/TokenVesting.sol
contract TokenVesting {
address public immutable beneficiary;
address public immutable token;
uint64 public immutable start;
uint64 public immutable cliffEnd;
uint64 public immutable vestingEnd;
uint256 public released;
event TokensReleased(uint256 amount);
constructor(
address _beneficiary,
uint64 _cliffDuration,
uint64 _vestingDuration,
address _token
) {
require(_beneficiary != address(0), "Zero beneficiary");
require(_token != address(0), "Zero token");
require(_vestingDuration > 0, "Zero vesting duration");
require(_cliffDuration <= _vestingDuration, "Cliff > vesting");
beneficiary = _beneficiary;
token = _token;
start = uint64(block.timestamp);
cliffEnd = uint64(block.timestamp) + _cliffDuration;
vestingEnd = uint64(block.timestamp) + _vestingDuration;
}
function totalAllocation() public view returns (uint256) {
return IERC20(token).balanceOf(address(this)) + released;
}
function vestedAmount(uint256 timestamp) public view returns (uint256) {
uint256 _totalAllocation = totalAllocation();
if (timestamp < cliffEnd) {
return 0;
} else if (timestamp >= vestingEnd) {
return _totalAllocation;
} else {
uint256 elapsed = timestamp - start;
uint256 duration = vestingEnd - start;
return (_totalAllocation * elapsed) / duration;
}
}
function releasable() public view returns (uint256) {
return vestedAmount(block.timestamp) - released;
}
function release() external {
uint256 amount = releasable();
require(amount > 0, "Nothing to release");
released += amount;
IERC20(token).transfer(beneficiary, amount);
emit TokensReleased(amount);
}
}
/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @dev Shared type declarations used by BOTH TokenTaxV2.sol (token-side) and
/// TokenFactoryTaxV2.sol (factory-side). Living in a tiny dedicated file
/// lets Solidity give them a single canonical type identity so that
/// structs passed across the factory/token boundary (e.g. `Helpers.Tax[]`
/// inside `CreateTokenParams`/`DeployTokenParams`) match cleanly.
/// Both the factory and the token's verification pages will include
/// this file, but it's pure interface/struct declarations — no
/// implementation bleeds across.
interface Helpers {
enum TaxType {
Burn,
ExternalBurn,
Dev,
Reflection,
Yield,
Liquify
}
enum TaxMoment {
Both,
Buy,
Sell
}
struct Tax {
uint256 id;
TaxType taxType;
TaxMoment taxMoment;
uint256 percentage;
address receiver;
address tokenAddress;
address burnAddress; //not used for ExternalBurn
bool rewardInPls; //not used for ExternalBurn
uint256 amountAccumulated;
}
function getBestPair(
address tokenA,
address tokenB,
address[] memory routers
) external view returns (address bestPair, address bestRouter);
function isPair(
address _address,
address _tokenAddress
) external view returns (bool);
function isBuy(
address _from,
address _to,
address _tokenAddress
) external view returns (bool);
function isSell(
address _from,
address _to,
address _tokenAddress
) external view returns (bool);
function getTokenWPLSPath(
address tokenAddress
) external pure returns (address[] memory path);
function getWPLSBuyBurnPath(
address tokenAddress
) external pure returns (address[] memory path);
function getProcessingAmount(
uint256 accumulatedAmount,
uint256 currentSwapAmount
)
external
pure
returns (uint256 processAmount, uint256 newAccumulatedAmount);
function calculateTaxAmount(
uint256 originalAmount,
uint256 taxPercentage,
uint256 Fee,
bool FeeEnabled,
uint256 globalDivider
) external pure returns (uint256 taxAmount, uint256 FeeAmount);
function hasAccumulatedTaxes(
Tax[] memory taxes
) external pure returns (bool);
function getTotalTaxs(Tax[] memory taxes) external pure returns (uint256);
function cleanPendingReflections(
address account,
address tokenAddress,
uint256 reflectionsPerShareAmount,
uint256 reflectionDebt,
uint256 precision
) external view returns (uint256);
function pendingYields(
address account,
address tokenAddress,
uint256 reflectionsPerShareAmount,
uint256 reflectionDebt,
uint256 precision
) external view returns (uint256);
function isExcludedFromTax(
address from,
address to,
address SmartTrader,
address deployer,
address thisContract
) external pure returns (bool);
function taxesInitialize(
Helpers.Tax[] memory _taxes
)
external
pure
returns (bool, bool, bool, Helpers.Tax[] memory, address[] memory);
function isDeadAddress(address _address) external pure returns (bool);
}
struct DeployTokenParams {
string name_;
string symbol_;
address owner_;
address mintTo;
uint256 initialSupply;
Helpers.Tax[] taxes;
address smartTrader;
address factory;
address helpers;
uint256 burnOnDeployPct;
address vestingContract;
uint256 vestAmount;
bool tradingEnabled;
uint64 enableTradingAt;
}
Compiler Settings
{"remappings":[":@1inch/solidity-utils/=lib/solidity-utils/",":@chainlink/=lib/foundry-chainlink-toolkit/",":@chainlink/contracts/=lib/foundry-chainlink-toolkit/lib/chainlink-brownie-contracts/contracts/src/",":@forge-std/=lib/forge-std/src/",":@gearbox-protocol/core-v2/=lib/core-v2/",":@gearbox-protocol/core-v3/=lib/core-v3/",":@gearbox-protocol/sdk-gov/=lib/sdk-gov/",":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",":@redstone-finance/=lib/integrations-v3/node_modules/@redstone-finance/",":@uniswap/v2-core/=lib/v2-core/",":@uniswap/v2-periphery/=lib/v2-periphery/",":chainlink-brownie-contracts/=lib/foundry-chainlink-toolkit/lib/chainlink-brownie-contracts/contracts/src/v0.6/vendor/@arbitrum/nitro-contracts/src/",":chainlink/=lib/chainlink/",":core-v2/=lib/core-v2/contracts/",":core-v3/=lib/core-v3/contracts/",":ds-test/=lib/forge-std/lib/ds-test/src/",":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",":forge-std/=lib/forge-std/src/",":foundry-chainlink-toolkit/=lib/foundry-chainlink-toolkit/",":foundry-devops/=lib/foundry-devops/",":halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",":integrations-v3/=lib/integrations-v3/",":openzeppelin-contracts copy/=lib/openzeppelin-contracts copy/",":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",":openzeppelin-contracts/=lib/openzeppelin-contracts/",":sdk-gov/=lib/sdk-gov/",":solidity-lib/=lib/solidity-lib/contracts/",":solidity-utils/=lib/solidity-utils/contracts/",":v2-core/=lib/v2-core/contracts/",":v2-periphery/=lib/v2-periphery/contracts/"],"optimizer":{"runs":1,"enabled":true},"metadata":{"bytecodeHash":"none"},"libraries":{},"evmVersion":"shanghai","compilationTarget":{"contracts/Tokens/TokenTaxV2.sol":"TokenTax"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"tuple","name":"p","internalType":"struct DeployTokenParams","components":[{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"symbol_","internalType":"string"},{"type":"address","name":"owner_","internalType":"address"},{"type":"address","name":"mintTo","internalType":"address"},{"type":"uint256","name":"initialSupply","internalType":"uint256"},{"type":"tuple[]","name":"taxes","internalType":"struct Helpers.Tax[]","components":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint8","name":"taxType","internalType":"enum Helpers.TaxType"},{"type":"uint8","name":"taxMoment","internalType":"enum Helpers.TaxMoment"},{"type":"uint256","name":"percentage","internalType":"uint256"},{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"burnAddress","internalType":"address"},{"type":"bool","name":"rewardInPls","internalType":"bool"},{"type":"uint256","name":"amountAccumulated","internalType":"uint256"}]},{"type":"address","name":"smartTrader","internalType":"address"},{"type":"address","name":"factory","internalType":"address"},{"type":"address","name":"helpers","internalType":"address"},{"type":"uint256","name":"burnOnDeployPct","internalType":"uint256"},{"type":"address","name":"vestingContract","internalType":"address"},{"type":"uint256","name":"vestAmount","internalType":"uint256"},{"type":"bool","name":"tradingEnabled","internalType":"bool"},{"type":"uint64","name":"enableTradingAt","internalType":"uint64"}]}]},{"type":"error","name":"AlreadyEnabled","inputs":[]},{"type":"error","name":"ERC20InsufficientAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"allowance","internalType":"uint256"},{"type":"uint256","name":"needed","internalType":"uint256"}]},{"type":"error","name":"ERC20InsufficientBalance","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"uint256","name":"balance","internalType":"uint256"},{"type":"uint256","name":"needed","internalType":"uint256"}]},{"type":"error","name":"ERC20InvalidApprover","inputs":[{"type":"address","name":"approver","internalType":"address"}]},{"type":"error","name":"ERC20InvalidReceiver","inputs":[{"type":"address","name":"receiver","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSender","inputs":[{"type":"address","name":"sender","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSpender","inputs":[{"type":"address","name":"spender","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"error","name":"TradingDisabled","inputs":[]},{"type":"error","name":"ZeroTaxPercentage","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":"BurnTaxProcessed","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExternalBurnProcessed","inputs":[{"type":"uint256","name":"tokenAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"taxid","internalType":"uint256","indexed":false},{"type":"uint256","name":"wethAmount","internalType":"uint256","indexed":false},{"type":"address","name":"receiver","internalType":"address","indexed":false},{"type":"address","name":"tokenToBurn","internalType":"address","indexed":false},{"type":"uint256","name":"timestamp","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":"ReflectionDistributed","inputs":[{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"fromAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"toAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"deployerAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"reflectionsPerShareAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ReflectionTaxProcessed","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"newReflectionsPerShareAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TaxCollected","inputs":[{"type":"uint256","name":"taxId","internalType":"uint256","indexed":true},{"type":"uint8","name":"taxType","internalType":"enum Helpers.TaxType","indexed":false},{"type":"uint8","name":"taxMoment","internalType":"enum Helpers.TaxMoment","indexed":false},{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","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":"YieldDistributed","inputs":[{"type":"address","name":"tokenAddress","internalType":"address","indexed":false},{"type":"address","name":"recipient","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"reflectionsPerShareAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"YieldTaxProcessed","inputs":[{"type":"uint256","name":"tokenAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"wethAmount","internalType":"uint256","indexed":false},{"type":"address","name":"yieldTokenAddress","internalType":"address","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"noRouter","inputs":[],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addTaxExclusion","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"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":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"burn","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"claimYield","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enableTrading","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"enableTradingAt","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"forceProcessAccumulatedTaxes","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentReflectionsPerShareAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNeonLpFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getNeonLpReceiver","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Helpers.Tax[]","components":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint8","name":"taxType","internalType":"enum Helpers.TaxType"},{"type":"uint8","name":"taxMoment","internalType":"enum Helpers.TaxMoment"},{"type":"uint256","name":"percentage","internalType":"uint256"},{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"burnAddress","internalType":"address"},{"type":"bool","name":"rewardInPls","internalType":"bool"},{"type":"uint256","name":"amountAccumulated","internalType":"uint256"}]}],"name":"getTaxes","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalTaxs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getWallet","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getYieldTokenReflectionDebts","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Manager.YieldToken[]","components":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"reflectionsPerShareAmount","internalType":"uint256"}]}],"name":"getYieldTokens","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getaccumulatedFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getaccumulatedNeonFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromReflections","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isReflectionExcluded","inputs":[{"type":"address","name":"","internalType":"address"}]},{"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":"uint256","name":"","internalType":"uint256"}],"name":"pendingReflections","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingYields","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"tokenIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"reapproveSmartTrader","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeTaxExclusion","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescuePLS","inputs":[{"type":"address","name":"to","internalType":"address payable"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueToken","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint8","name":"taxType","internalType":"enum Helpers.TaxType"},{"type":"uint8","name":"taxMoment","internalType":"enum Helpers.TaxMoment"},{"type":"uint256","name":"percentage","internalType":"uint256"},{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"burnAddress","internalType":"address"},{"type":"bool","name":"rewardInPls","internalType":"bool"},{"type":"uint256","name":"amountAccumulated","internalType":"uint256"}],"name":"taxes","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalBurned","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalLiquify","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalReflection","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupport","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalYield","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":"value","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":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateTaxReceiver","inputs":[{"type":"uint256","name":"taxId","internalType":"uint256"},{"type":"address","name":"newReceiver","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateTaxTokenAddress","inputs":[{"type":"uint256","name":"taxId","internalType":"uint256"},{"type":"address","name":"newTokenAddress","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x6101006040527398bf93ebf5c380c0e6ae8e192a7e2ae08edacc02608090815273165c3410fc91ef562c50559f7d2289febed552d960a05273cc73b59f8d7b7c532703bdfea2808a28a488cf4760c05273eb45a3c4aedd0f47f345fb4c8a1802bb5740d72560e052610075906012906004611018565b50348015610081575f5ffd5b506040516165ff3803806165ff8339810160408190526100a091611313565b60408101518151602083015160036100b88382611505565b5060046100c58282611505565b5050506001600160a01b0381166100fa575f604051631e4fbdf760e01b81526004016100f191906115bf565b60405180910390fd5b61010381610421565b50610180810151600f80546101a08401516001600160401b031661010002610100600160481b0319931515939093166001600160481b031990911617919091179055606081015160808201516101599190610472565b6101208101511561019f575f612710826101200151836080015161017d91906115e7565b61018791906115fe565b905061019d8260600151826104aa60201b60201c565b505b5f8161016001511180156101c057506101408101516001600160a01b031615155b156101e4576101e481606001518261014001518361016001516104de60201b60201c565b6060810151601080546001600160a01b039283166001600160a01b0319918216179091556080830151600e5560c0830151600f8054918416690100000000000000000002600160481b600160e81b031990921691909117905560e08301516011805491909316911617905560a081015161025d90610540565b6103376010546001600160a01b039081165f908152601360205260408082208054600160ff1991821681179092553084528284208054821683179055600f5469010000000000000000009004851684528284208054821683179055601154909416835290822080548416821790557f57cf93e0db3e0da914216c2f0e12ee44cd857ba192417d87569e725c63b18eab8054841682179055735df85211aa383994b03a52946b91329c25e622e99091527f77941af77031539170e7eb298cf7e6530caa0379750b8de97db66d0a13c808cc8054909216179055565b601754610100900460ff1680610355575060175462010000900460ff165b1561036257610362610c6b565b600f5460405163095ea7b360e01b815269010000000000000000009091046001600160a01b031660048201525f19602482015273a1077a294dde1b09bb078844df40758a5d0f9a279063095ea7b3906044016020604051808303815f875af11580156103d0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f4919061161d565b50600f5461041b903090690100000000000000000090046001600160a01b03165f19610d14565b5061168b565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b03821661049b575f60405163ec442f0560e01b81526004016100f191906115bf565b6104a65f8383610d21565b5050565b6001600160a01b0382166104d3575f604051634b637e8f60e11b81526004016100f191906115bf565b6104a6825f83610d21565b6001600160a01b038316610507575f604051634b637e8f60e11b81526004016100f191906115bf565b6001600160a01b038216610530575f60405163ec442f0560e01b81526004016100f191906115bf565b61053b838383610d21565b505050565b5f5f5b8251811015610c185760188382815181106105605761056061163d565b6020908102919091018101518254600181810185555f94855293839020825160079092020190815591810151828401805492949192909160ff19909116908360058111156105b0576105b0611651565b0217905550604082015160018201805461ff0019166101008360028111156105da576105da611651565b02179055506060820151600282015560808201516003820180546001600160a01b039283166001600160a01b03199182161790915560a08401516004840180549184169190921617905560c083015160058301805460e08601511515600160a01b026001600160a81b0319909116929093169190911791909117905561010090910151600690910155601880548291908290811061067a5761067a61163d565b905f5260205f2090600702015f018190555082818151811061069e5761069e61163d565b6020026020010151606001515f036106c957604051632e3d979b60e21b815260040160405180910390fd5b6113888382815181106106de576106de61163d565b60200260200101516060015111156107385760405162461bcd60e51b815260206004820152601760248201527f5461782070657263656e7461676520746f6f206869676800000000000000000060448201526064016100f1565b5f83828151811061074b5761074b61163d565b602002602001015160400151600281111561076857610768611651565b036107a85782818151811061077f5761077f61163d565b602002602001015160600151600261079791906115e7565b6107a19083611665565b91506107d4565b8281815181106107ba576107ba61163d565b602002602001015160600151826107d19190611665565b91505b60038382815181106107e8576107e861163d565b602002602001015160200151600581111561080557610805611651565b0361081a576017805461ff0019166101001790555b600483828151811061082e5761082e61163d565b602002602001015160200151600581111561084b5761084b611651565b036108bf576017805462ff000019166201000017905582515f908490839081106108775761087761163d565b602002602001015160a001516001600160a01b0316146108bf576108bd8382815181106108a6576108a661163d565b602002602001015160a00151610e4760201b60201c565b505b60018382815181106108d3576108d361163d565b60200260200101516020015160058111156108f0576108f0611651565b03610a23575f6001600160a01b03168382815181106109115761091161163d565b6020026020010151608001516001600160a01b0316036109815760405162461bcd60e51b815260206004820152602560248201527f45787465726e616c4275726e3a2072656365697665722063616e6e6f74206265604482015264207a65726f60d81b60648201526084016100f1565b5f6001600160a01b031683828151811061099d5761099d61163d565b602002602001015160a001516001600160a01b031603610a115760405162461bcd60e51b815260206004820152602960248201527f45787465726e616c4275726e3a20746f6b656e416464726573732063616e6e6f60448201526874206265207a65726f60b81b60648201526084016100f1565b6017805460ff19166001179055610c10565b6002838281518110610a3757610a3761163d565b6020026020010151602001516005811115610a5457610a54611651565b03610b0d575f6001600160a01b0316838281518110610a7557610a7561163d565b6020026020010151608001516001600160a01b031603610ad75760405162461bcd60e51b815260206004820152601c60248201527f4465763a2072656365697665722063616e6e6f74206265207a65726f0000000060448201526064016100f1565b828181518110610ae957610ae961163d565b602002602001015160e0015115610b08576017805460ff191660011790555b610c10565b6004838281518110610b2157610b2161163d565b6020026020010151602001516005811115610b3e57610b3e611651565b03610bcc575f6001600160a01b0316838281518110610b5f57610b5f61163d565b602002602001015160a001516001600160a01b031603610a115760405162461bcd60e51b815260206004820152602260248201527f5969656c643a20746f6b656e416464726573732063616e6e6f74206265207a65604482015261726f60f01b60648201526084016100f1565b6005838281518110610be057610be061163d565b6020026020010151602001516005811115610bfd57610bfd611651565b03610c10576017805460ff191660011790555b600101610543565b50611f408111156104a65760405162461bcd60e51b815260206004820152601d60248201527f546f74616c207461782070657263656e7461676520746f6f206869676800000060448201526064016100f1565b600a6020527f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e38054600160ff199182168117909255305f90815260408120805490921690921790555b601254811015610d11576001600a5f60128481548110610cd657610cd661163d565b5f918252602080832091909101546001600160a01b031683528201929092526040019020805460ff1916911515919091179055600101610cb4565b50565b61053b8383836001610f45565b6001600160a01b038316610d4b578060025f828254610d409190611665565b90915550610dbb9050565b6001600160a01b0383165f9081526020819052604090205481811015610d9d5760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016100f1565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610dd757600280548290039055610df5565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610e3a91815260200190565b60405180910390a3505050565b5f805b600654811015610e9d57826001600160a01b031660068281548110610e7157610e7161163d565b5f9182526020909120600290910201546001600160a01b031603610e955792915050565b600101610e4a565b50604080518082019091526001600160a01b0383811682525f6020830181815260068054600180820183559382905294517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f600290960295860180546001600160a01b0319169190951617909355517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d409093019290925554610f3f9190611678565b92915050565b6001600160a01b038416610f6e575f60405163e602df0560e01b81526004016100f191906115bf565b6001600160a01b038316610f97575f604051634a1406b160e11b81526004016100f191906115bf565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561101257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161100991815260200190565b60405180910390a35b50505050565b828054828255905f5260205f2090810192821561106b579160200282015b8281111561106b57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611036565b5061107792915061107b565b5090565b5b80821115611077575f815560010161107c565b634e487b7160e01b5f52604160045260245ffd5b60405161012081016001600160401b03811182821017156110c6576110c661108f565b60405290565b6040516101c081016001600160401b03811182821017156110c6576110c661108f565b604051601f8201601f191681016001600160401b03811182821017156111175761111761108f565b604052919050565b5f82601f83011261112e575f5ffd5b81516001600160401b038111156111475761114761108f565b61115a601f8201601f19166020016110ef565b81815284602083860101111561116e575f5ffd5b5f5b8281101561118c57602081860181015183830182015201611170565b505f918101602001919091529392505050565b80516001600160a01b03811681146111b5575f5ffd5b919050565b8051600681106111b5575f5ffd5b8051600381106111b5575f5ffd5b805180151581146111b5575f5ffd5b5f82601f8301126111f4575f5ffd5b81516001600160401b0381111561120d5761120d61108f565b61121c60208260051b016110ef565b808282526020820191506020610120840286010192508583111561123e575f5ffd5b602085015b838110156112f357610120818803121561125b575f5ffd5b6112636110a3565b81518152611273602083016111ba565b6020820152611284604083016111c8565b60408201526060828101519082015261129f6080830161119f565b60808201526112b060a0830161119f565b60a08201526112c160c0830161119f565b60c08201526112d260e083016111d6565b60e08201526101008281015190820152835260209092019161012001611243565b5095945050505050565b80516001600160401b03811681146111b5575f5ffd5b5f60208284031215611323575f5ffd5b81516001600160401b03811115611338575f5ffd5b82016101c0818503121561134a575f5ffd5b6113526110cc565b81516001600160401b03811115611367575f5ffd5b6113738682850161111f565b82525060208201516001600160401b0381111561138e575f5ffd5b61139a8682850161111f565b6020830152506113ac6040830161119f565b60408201526113bd6060830161119f565b60608201526080828101519082015260a08201516001600160401b038111156113e4575f5ffd5b6113f0868285016111e5565b60a08301525061140260c0830161119f565b60c082015261141360e0830161119f565b60e0820152611425610100830161119f565b6101008201526101208281015190820152611443610140830161119f565b610140820152610160828101519082015261146161018083016111d6565b6101808201526114746101a083016112fd565b6101a0820152949350505050565b600181811c9082168061149657607f821691505b6020821081036114b457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561053b57805f5260205f20601f840160051c810160208510156114df5750805b601f840160051c820191505b818110156114fe575f81556001016114eb565b5050505050565b81516001600160401b0381111561151e5761151e61108f565b6115328161152c8454611482565b846114ba565b6020601f821160018114611564575f831561154d5750848201515b5f19600385901b1c1916600184901b1784556114fe565b5f84815260208120601f198516915b828110156115935787850151825560209485019460019092019101611573565b50848210156115b057868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610f3f57610f3f6115d3565b5f8261161857634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561162d575f5ffd5b611636826111d6565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b80820180821115610f3f57610f3f6115d3565b81810381811115610f3f57610f3f6115d3565b614f67806116985f395ff3fe60806040526004361061021a575f3560e01c8063014182051461022557806306fdde031461024d578063095ea7b31461026e5780630d3ebcbf1461029d57806313299604146102b3578063138dd4d1146102d457806318160ddd146102e857806322849720146102fc57806323b872dd146103115780632973ef2d14610330578063313ce56714610351578063346847b41461036c578063378dc3dc14610380578063406cf2291461039557806342966c68146103a95780634ada218b146103c85780634f30800d146103e157806358232c94146103f5578063695d69b3146104145780636a2072d414610433578063709df63c1461045f57806370a0823114610480578063715018a61461049f5780637922fc01146104b35780637c8b6f09146104c857806384527bbd146105045780638453ef99146105195780638a8c523c1461052d5780638da5cb5b146105415780639045be581461055557806390b8e5981461058357806395d89b41146105a25780639b165f4e146105b6578063a9059cbb146105d5578063ad826ab6146105f4578063b2ff197314610613578063c5be2bc714610627578063cb78c1631461065b578063ce7b63ed1461066f578063ced72f8714610683578063d89135cd14610697578063dd62ed3e146106ac578063e4f8d62e146106cb578063e5711e8b146106ea578063e6375d3e14610709578063eb50c06114610728578063f2fde38b14610747575f5ffd5b3661022157005b5f5ffd5b348015610230575f5ffd5b5061023a601c5481565b6040519081526020015b60405180910390f35b348015610258575f5ffd5b50610261610766565b604051610244919061455f565b348015610279575f5ffd5b5061028d6102883660046145be565b6107f6565b6040519015158152602001610244565b3480156102a8575f5ffd5b506102b161080f565b005b3480156102be575f5ffd5b506102c7610839565b60405161024491906145f5565b3480156102df575f5ffd5b506102c76108a9565b3480156102f3575f5ffd5b5060025461023a565b348015610307575f5ffd5b5061023a601b5481565b34801561031c575f5ffd5b5061028d61032b366004614609565b6108f0565b34801561033b575f5ffd5b50610344610913565b604051610244919061467f565b34801561035c575f5ffd5b5060405160128152602001610244565b348015610377575f5ffd5b5061023a610a42565b34801561038b575f5ffd5b5061023a600e5481565b3480156103a0575f5ffd5b5061028d610aad565b3480156103b4575f5ffd5b506102b16103c336600461474d565b610abe565b3480156103d3575f5ffd5b50600f5461028d9060ff1681565b3480156103ec575f5ffd5b5060075461023a565b348015610400575f5ffd5b506102b161040f366004614764565b610b08565b34801561041f575f5ffd5b5061023a61042e366004614792565b610bd9565b34801561043e575f5ffd5b5061045261044d366004614792565b610bf8565b60405161024491906147ad565b34801561046a575f5ffd5b50610473610c61565b60405161024491906147e4565b34801561048b575f5ffd5b5061023a61049a366004614792565b610ccb565b3480156104aa575f5ffd5b506102b1610ce5565b3480156104be575f5ffd5b5061023a601d5481565b3480156104d3575f5ffd5b50600f546104ec9061010090046001600160401b031681565b6040516001600160401b039091168152602001610244565b34801561050f575f5ffd5b5061023a601a5481565b348015610524575f5ffd5b506102b1610cf6565b348015610538575f5ffd5b506102b1610d08565b34801561054c575f5ffd5b506102c7610d58565b348015610560575f5ffd5b5061028d61056f366004614792565b600a6020525f908152604090205460ff1681565b34801561058e575f5ffd5b506102b161059d3660046145be565b610d67565b3480156105ad575f5ffd5b50610261610ea1565b3480156105c1575f5ffd5b506102b16105d0366004614792565b610eb0565b3480156105e0575f5ffd5b5061028d6105ef3660046145be565b610edb565b3480156105ff575f5ffd5b506102b161060e366004614764565b610ee8565b34801561061e575f5ffd5b5060165461023a565b348015610632575f5ffd5b5061064661064136600461474d565b610fb1565b60405161024499989796959493929190614830565b348015610666575f5ffd5b5061023a611026565b34801561067a575f5ffd5b5060155461023a565b34801561068e575f5ffd5b5061023a611073565b3480156106a2575f5ffd5b5061023a60195481565b3480156106b7575f5ffd5b5061023a6106c636600461488f565b6110ba565b3480156106d6575f5ffd5b5061023a6106e53660046145be565b6110e4565b3480156106f5575f5ffd5b506102b1610704366004614609565b6111fa565b348015610714575f5ffd5b5061028d610723366004614792565b611364565b348015610733575f5ffd5b506102b1610742366004614792565b611381565b348015610752575f5ffd5b506102b1610761366004614792565b6113a9565b606060038054610775906148bb565b80601f01602080910402602001604051908101604052809291908181526020018280546107a1906148bb565b80156107ec5780601f106107c3576101008083540402835291602001916107ec565b820191905f5260205f20905b8154815290600101906020018083116107cf57829003601f168201915b5050505050905090565b5f336108038185856113e3565b60019150505b92915050565b6108176113f0565b600f54610837903090600160481b90046001600160a01b03165f196113e3565b565b601154604080516336ce6de360e11b815290515f926001600160a01b031691636d9cdbc69160048083019260209291908290030181865afa158015610880573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a49190614903565b905090565b60115460408051637bb8996d60e01b815290515f926001600160a01b031691637bb8996d9160048083019260209291908290030181865afa158015610880573d5f5f3e3d5ffd5b5f336108fd858285611422565b61090885858561146d565b506001949350505050565b60606018805480602002602001604051908101604052809291908181526020015f905b82821015610a39578382905f5260205f209060070201604051806101200160405290815f8201548152602001600182015f9054906101000a900460ff16600581111561098457610984614647565b600581111561099557610995614647565b81526020016001820160019054906101000a900460ff1660028111156109bd576109bd614647565b60028111156109ce576109ce614647565b8152600282015460208083019190915260038301546001600160a01b03908116604084015260048401548116606084015260058401549081166080840152600160a01b900460ff16151560a083015260069092015460c0909101529082526001929092019101610936565b50505050905090565b6011546040805163b5a08dd160e01b815290515f926001600160a01b03169163b5a08dd19160048083019260209291908290030181865afa158015610a89573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a4919061491e565b5f610ab833336116f1565b50600190565b8060195f828254610acf9190614949565b90915550506040515f516020614e9b5f395f51905f5290610af3908390429061495c565b60405180910390a1610b05338261171f565b50565b610b106113f0565b6018548210610b3a5760405162461bcd60e51b8152600401610b319061496a565b60405180910390fd5b6001600160a01b038116610b8f5760405162461bcd60e51b815260206004820152601c60248201527b546f6b656e20616464726573732063616e6e6f74206265207a65726f60201b6044820152606401610b31565b8060188381548110610ba357610ba3614992565b905f5260205f2090600702016004015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b5f610be382611364565b15610bef57505f919050565b61080982611753565b6001600160a01b0381165f908152600c6020908152604091829020805483518184028101840190945280845260609392830182828015610c5557602002820191905f5260205f20905b815481526020019060010190808311610c41575b50505050509050919050565b60606006805480602002602001604051908101604052809291908181526020015f905b82821015610a39575f848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610c84565b6001600160a01b03165f9081526020819052604090205490565b610ced6113f0565b6108375f6117f0565b610cfe6113f0565b6108375f19611841565b610d106113f0565b600f5460ff1615610d3457604051637952fbad60e11b815260040160405180910390fd5b600f805460ff191660011790556040515f516020614efb5f395f51905f52905f90a1565b6005546001600160a01b031690565b60115f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610db7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddb9190614903565b6001600160a01b0316336001600160a01b031614610e0b5760405162461bcd60e51b8152600401610b31906149a6565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610e54576040519150601f19603f3d011682016040523d82523d5f602084013e610e59565b606091505b5050905080610e9c5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610b31565b505050565b606060048054610775906148bb565b610eb86113f0565b6001600160a01b03165f908152601360205260409020805460ff19166001179055565b5f3361080381858561146d565b610ef06113f0565b6018548210610f115760405162461bcd60e51b8152600401610b319061496a565b6001600160a01b038116610f675760405162461bcd60e51b815260206004820152601f60248201527f52656365697665722063616e6e6f74206265207a65726f2061646472657373006044820152606401610b31565b8060188381548110610f7b57610f7b614992565b905f5260205f2090600702016003015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b60188181548110610fc0575f80fd5b5f918252602090912060079091020180546001820154600283015460038401546004850154600586015460069096015494965060ff8085169661010090950481169593946001600160a01b039384169492841693811692600160a01b9091049091169089565b604051625f8d8f60e81b81525f905f516020614ebb5f395f51905f5290635f8d8f0090611058906018906004016149de565b602060405180830381865afa158015610a89573d5f5f3e3d5ffd5b6011546040805163c57981b560e01b815290515f926001600160a01b03169163c57981b59160048083019260209291908290030181865afa158015610a89573d5f5f3e3d5ffd5b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6001600160a01b0382165f908152600c6020526040812054821061110957505f610809565b5f516020614ebb5f395f51905f526001600160a01b031663a89055e584306006868154811061113a5761113a614992565b905f5260205f20906002020160010154600c5f896001600160a01b03166001600160a01b031681526020019081526020015f20878154811061117e5761117e614992565b905f5260205f2001546b204fce5e3e250261100000006040518663ffffffff1660e01b81526004016111b4959493929190614abf565b602060405180830381865afa1580156111cf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f3919061491e565b9392505050565b60115f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561124a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061126e9190614903565b6001600160a01b0316336001600160a01b03161461129e5760405162461bcd60e51b8152600401610b31906149a6565b306001600160a01b038416036112f05760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103932b9b1bab29037bbb7103a37b5b2b760491b6044820152606401610b31565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061131e9085908590600401614af0565b6020604051808303815f875af115801561133a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135e9190614b09565b50505050565b6001600160a01b03165f908152600a602052604090205460ff1690565b6113896113f0565b6001600160a01b03165f908152601360205260409020805460ff19169055565b6113b16113f0565b6001600160a01b0381166113da575f604051631e4fbdf760e01b8152600401610b3191906145f5565b610b05816117f0565b610e9c8383836001612322565b336113f9610d58565b6001600160a01b031614610837573360405163118cdaa760e01b8152600401610b3191906145f5565b5f61142d84846110ba565b90505f1981101561135e578181101561145f57828183604051637dc7a0d960e11b8152600401610b3193929190614b28565b61135e84848484035f612322565b6017805460ff60201b19169055600f546001600160a01b0384165f9081526013602052604090205460ff9182169116811580156114b95750600f5461010090046001600160401b031615155b80156114d55750600f5461010090046001600160401b03164210155b1561150357600f805460ff191660019081179091556040519092505f516020614efb5f395f51905f52905f90a15b61150c846123f4565b156115225761151b858461171f565b5050505050565b8115801561152e575080155b1561154c5760405163bcb8b8fb60e01b815260040160405180910390fd5b5f6115568561242c565b601854909150158061157257506017546301000000900460ff16155b8061157a5750815b8061159c57506001600160a01b0385165f9081526013602052604090205460ff165b806115a95750600d5460ff165b156115fb576017546301000000900460ff161580156115c55750805b156115de576017805463ff000000191663010000001790555b6115e886866116f1565b6115f38686866124a7565b505050505050565b80801561162057506001600160a01b0385165f908152600a602052604090205460ff16155b15611648576001600160a01b0385165f908152600a60205260409020805460ff191660011790555b5f6116538787612504565b90505f8161166a576116658888612579565b61166c565b5f5b90505f61167c89898986866125d4565b60175490915060ff16801561169b5750601754600160201b900460ff16155b80156116a5575082155b156116c7576116b387611841565b6017805460ff60201b1916600160201b1790555b6116d189896116f1565b6116db898961289c565b6116e68989836124a7565b505050505050505050565b60175462010000900460ff161561171b5760105461171b90839083906001600160a01b031661299a565b5050565b6001600160a01b038216611748575f604051634b637e8f60e11b8152600401610b3191906145f5565b61171b825f83612e51565b6007546001600160a01b0382165f90815260096020526040808220549051631d2fa43b60e11b815291925f516020614ebb5f395f51905f5292633a5f4876926117b19287923092906b204fce5e3e2502611000000090600401614abf565b602060405180830381865afa1580156117cc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610809919061491e565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b600d805460ff191660011790556018545f90819081816001600160401b0381111561186e5761186e614b49565b604051908082528060200260200182016040528015611897578160200160208202803683370190505b5090505f826001600160401b038111156118b3576118b3614b49565b6040519080825280602002602001820160405280156118dc578160200160208202803683370190505b5090505f5b83811015611b44575f601882815481106118fd576118fd614992565b905f5260205f209060070201905080600601545f0361191c5750611b3c565b60018082015460ff16600581111561193657611936614647565b148061197057506002600182015460ff16600581111561195857611958614647565b14801561197057506005810154600160a01b900460ff165b8061199357506004600182015460ff16600581111561199157611991614647565b145b806119b657506005600182015460ff1660058111156119b4576119b4614647565b145b15611b3a57600681015460405163059b6d4760e21b81525f9182915f516020614ebb5f395f51905f529163166db51c916119f591908e9060040161495c565b6040805180830381865afa158015611a0f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a339190614b5d565b90925090508115611b0f5781816005600186015460ff166005811115611a5b57611a5b614647565b03611a8457611a6b600285614b7f565b9150611a778285614b9e565b611a819084614949565b90505b6001888781518110611a9857611a98614992565b60200260200101901515908115158152505081878781518110611abd57611abd614992565b6020908102919091010152611ad2828c614949565b9a5089611ade81614bb1565b9a50508060188781548110611af557611af5614992565b905f5260205f209060070201600601819055505050611b37565b8060188581548110611b2357611b23614992565b905f5260205f209060070201600601819055505b50505b505b6001016118e1565b50604051632a8ddb2f60e01b81525f905f516020614ebb5f395f51905f5290632a8ddb2f90611b899030905f516020614f1b5f395f51905f5290601290600401614bc9565b6040805180830381865afa158015611ba3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bc79190614c35565b9150506001600160a01b038116611c0b576040517f34be9cb68ddf4eeebba29ea0e1db420286ea39e4ce7a377e66a7b47a998a6d03905f90a1505050505050612315565b5f5f5f5f5f516020614ebb5f395f51905f526001600160a01b031663166db51c6015548d6040518363ffffffff1660e01b8152600401611c4c92919061495c565b6040805180830381865afa158015611c66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c8a9190614b5d565b60165460405163059b6d4760e21b81529296509093505f516020614ebb5f395f51905f529163166db51c91611cc3918f9060040161495c565b6040805180830381865afa158015611cdd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d019190614b5d565b601593909355601692909255509050611d1a8289614949565b9750611d268189614949565b9750875f03611d3c575050505050505050612315565b600f54600160481b90046001600160a01b0316637e18437984308b611d6082612f64565b6040518563ffffffff1660e01b8152600401611d7f9493929190614c62565b5f604051808303815f87803b158015611d96575f5ffd5b505af1925050508015611da7575060015b611e69575f5b86811015611e2c57858181518110611dc757611dc7614992565b602002602001015115611e2457848181518110611de657611de6614992565b602002602001015160188281548110611e0157611e01614992565b905f5260205f2090600702016006015f828254611e1e9190614949565b90915550505b600101611dad565b508160155f828254611e3e9190614949565b925050819055508060165f828254611e569190614949565b9091555061231598505050505050505050565b6008546040516370a0823160e01b81525f91905f516020614f1b5f395f51905f52906370a0823190611e9f9030906004016145f5565b602060405180830381865afa158015611eba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ede919061491e565b611ee89190614b9e565b9050611ef68184848c612fd8565b611f009082614b9e565b9050611f0c838a614b9e565b9850611f18828a614b9e565b9850805f03611f2f57505050505050505050612315565b5f5b8781101561230a57868181518110611f4b57611f4b614992565b60200260200101511580611f775750858181518110611f6c57611f6c614992565b60200260200101515f145b612302575f8a83888481518110611f9057611f90614992565b6020026020010151611fa29190614cd3565b611fac9190614b7f565b90505f60188381548110611fc257611fc2614992565b5f9182526020909120600790910201905060018082015460ff166005811115611fed57611fed614647565b03612133575f516020614e7b5f395f51905f5288848151811061201257612012614992565b602090810291909101015182546003840154600485015460405161204a94939288926001600160a01b03918216929116904290614cea565b60405180910390a160408051610120810190915281548152600182015461212e9184918490602083019060ff16600581111561208857612088614647565b600581111561209957612099614647565b81526020016001820160019054906101000a900460ff1660028111156120c1576120c1614647565b60028111156120d2576120d2614647565b81526002820154602082015260038201546001600160a01b03908116604083015260048301548116606083015260058301549081166080830152600160a01b900460ff16151560a082015260069091015460c090910152613061565b6122ff565b6002600182015460ff16600581111561214e5761214e614647565b14801561216657506005810154600160a01b900460ff165b1561218457600381015461212e9083906001600160a01b031661324e565b6004600182015460ff16600581111561219f5761219f614647565b036122d5575f516020614edb5f395f51905f528884815181106121c4576121c4614992565b602090810291909101015160048301546040516121f1929186916001600160a01b03909116904290614d1e565b60405180910390a160408051610120810190915281548152600182015461212e9184918490602083019060ff16600581111561222f5761222f614647565b600581111561224057612240614647565b81526020016001820160019054906101000a900460ff16600281111561226857612268614647565b600281111561227957612279614647565b81526002820154602082015260038201546001600160a01b03908116604083015260048301548116606083015260058301549081166080830152600160a01b900460ff16151560a082015260069091015460c09091015261336c565b6005600182015460ff1660058111156122f0576122f0614647565b036122ff576122ff828261377d565b50505b600101611f31565b505050505050505050505b50600d805460ff19169055565b6001600160a01b03841661234b575f60405163e602df0560e01b8152600401610b3191906145f5565b6001600160a01b038316612374575f604051634a1406b160e11b8152600401610b3191906145f5565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561135e57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516123e691815260200190565b60405180910390a350505050565b5f6001600160a01b038216158061241557506103696001600160a01b038316145b806108095750506001600160a01b031661dead1490565b604051630d5c7b5d60e41b81526001600160a01b03821660048201523060248201525f905f516020614ebb5f395f51905f529063d5c7b5d090604401602060405180830381865afa158015612483573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108099190614b09565b6001600160a01b0383166124d0575f604051634b637e8f60e11b8152600401610b3191906145f5565b6001600160a01b0382166124f9575f60405163ec442f0560e01b8152600401610b3191906145f5565b610e9c838383612e51565b604051636468b51760e01b81525f905f516020614ebb5f395f51905f5290636468b5179061253a90869086903090600401614d42565b602060405180830381865afa158015612555573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f39190614b09565b5f6125838361242c565b801561259357506125938261242c565b156125a057506001610809565b60405163154b004960e31b81525f516020614ebb5f395f51905f529063aa5802489061253a90869086903090600401614d42565b6040805160e0810182525f60a0820181905260c082018190526001600160a01b03888116835287166020830152918101859052831515606082015282151560808201526017548291829182919060ff16801561264057505f6126346108a9565b6001600160a01b031614155b156126535761264d610a42565b60a08201525b61265b611073565b60c082015260188054604080516020808402820181019092528281525f9390929091849084015b82821015612785578382905f5260205f209060070201604051806101200160405290815f8201548152602001600182015f9054906101000a900460ff1660058111156126d0576126d0614647565b60058111156126e1576126e1614647565b81526020016001820160019054906101000a900460ff16600281111561270957612709614647565b600281111561271a5761271a614647565b8152600282015460208083019190915260038301546001600160a01b03908116604084015260048401548116606084015260058401549081166080840152600160a01b900460ff16151560a083015260069092015460c0909101529082526001929092019101612682565b505082519293505f9150505b818110156127f9575f5f5f6127bf878786815181106127b2576127b2614992565b6020026020010151613ce9565b919450925090506127d0838b614949565b99506127dc828a614949565b98506127e88189614949565b975050600190920191506127919050565b5084156128445760175460ff1615612832576128168c30876124a7565b8460155f8282546128279190614949565b909155506128449050565b6128448c61283e610839565b876124a7565b831561286c576128558c30866124a7565b8360165f8282546128669190614949565b90915550505b8385612878888d614b9e565b6128829190614b9e565b61288c9190614b9e565b9c9b505050505050505050505050565b601754610100900460ff166128af575050565b6010545f90819081906128ce90869086906001600160a01b0316613e23565b600754604080516001600160a01b03808c1682528a166020820152908101859052606081018490526080810183905260a08101919091524260c082015292955090935091507f7f2255e92a9403cf8dd4b9f679ad1f5f5ce9226dd19b0faf14c84bace34d235b9060e00160405180910390a1821561295e5761294f8561242c565b61295e5761295e3086856124a7565b811561297c5761296d8461242c565b61297c5761297c3085846124a7565b801561151b5760105461151b9030906001600160a01b0316836124a7565b5f5b60065481101561135e575b6001600160a01b0384165f908152600c60205260409020548110612a18576001600160a01b0384165f908152600c6020526040902060068054839081106129f0576129f0614992565b5f918252602080832060016002909302018201548454928301855593835290912001556129a7565b6001600160a01b0383165f908152600c60205260409020548110612a89576001600160a01b0383165f908152600c602052604090206006805483908110612a6157612a61614992565b5f91825260208083206001600290930201820154845492830185559383529091200155612a18565b6001600160a01b0382165f908152600c60205260409020548110612afa576001600160a01b0382165f908152600c602052604090206006805483908110612ad257612ad2614992565b5f91825260208083206001600290930201820154845492830185559383529091200155612a89565b5f612b0485611364565b612b1757612b1285836110e4565b612b19565b5f5b90505f6001600160a01b0386811690861614612b5057612b3885611364565b612b4b57612b4685846110e4565b612b4d565b5f5b90505b6040805160028082526060820183525f9260208301908036833750506040805160028082526060820183529394505f93909250906020830190803683370190505090505f8415612bf25784838281518110612bad57612bad614992565b60200260200101818152505088828281518110612bcc57612bcc614992565b6001600160a01b039092166020928302919091019091015280612bee81614bb1565b9150505b8315612c505783838281518110612c0b57612c0b614992565b60200260200101818152505087828281518110612c2a57612c2a614992565b6001600160a01b039092166020928302919091019091015280612c4c81614bb1565b9150505b5f5b81811015612e3f575f848281518110612c6d57612c6d614992565b60200260200101511115612e375760068781548110612c8e57612c8e614992565b5f91825260209091206002909102015483516001600160a01b039091169063a9059cbb90859084908110612cc457612cc4614992565b6020026020010151868481518110612cde57612cde614992565b60200260200101516040518363ffffffff1660e01b8152600401612d03929190614af0565b6020604051808303815f875af1925050508015612d3d575060408051601f3d908101601f19168201909252612d3a91810190614b09565b60015b15612e3757505f516020614f1b5f395f51905f526001600160a01b031660068881548110612d6d57612d6d614992565b5f9182526020909120600290910201546001600160a01b031603612dbb57838181518110612d9d57612d9d614992565b602002602001015160085f828254612db59190614b9e565b90915550505b60068781548110612dce57612dce614992565b905f5260205f20906002020160010154600c5f858481518110612df357612df3614992565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208881548110612e2b57612e2b614992565b5f918252602090912001555b600101612c52565b50506001909401935061299c92505050565b6001600160a01b038316612e7b578060025f828254612e709190614949565b90915550612ed89050565b6001600160a01b0383165f9081526020819052604090205481811015612eba5783818360405163391434e360e21b8152600401610b3193929190614b28565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216612ef457600280548290039055612f12565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612f5791815260200190565b60405180910390a3505050565b6040516343d7ef9f60e11b81526060905f516020614ebb5f395f51905f52906387afdf3e90612f979085906004016145f5565b5f60405180830381865afa158015612fb1573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108099190810190614d65565b5f8082612fe58688614cd3565b612fef9190614b7f565b905080156130085761300881613003610839565b61324e565b5f836130148689614cd3565b61301e9190614b7f565b9050801561304c575f61302f6108a9565b90506001600160a01b0381161561304a5761304a828261324e565b505b6130568183614949565b979650505050505050565b815f0361306c575050565b5f516020614f1b5f395f51905f526001600160a01b03168160a001516001600160a01b03160361310c57608081015160405163a9059cbb60e01b81525f516020614f1b5f395f51905f529163a9059cbb916130cc91908690600401614af0565b6020604051808303815f875af11580156130e8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e9c9190614b09565b60a0810151604051632a8ddb2f60e01b81525f915f516020614ebb5f395f51905f5291632a8ddb2f91613154915f516020614f1b5f395f51905f529190601290600401614bc9565b6040805180830381865afa15801561316e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131929190614c35565b915050600f60099054906101000a90046001600160a01b03166001600160a01b0316635a9ac706828460800151866131cd8760a00151613eed565b6040518563ffffffff1660e01b81526004016131ec9493929190614c62565b5f604051808303815f87803b158015613203575f5ffd5b505af1925050508015613214575060015b610e9c57608082015160405163a9059cbb60e01b81525f516020614f1b5f395f51905f529163a9059cbb9161131e91908790600401614af0565b815f03613259575050565b604051632e1a7d4d60e01b8152600481018390525f516020614f1b5f395f51905f5290632e1a7d4d906024015f604051808303815f87803b15801561329c575f5ffd5b505af19250505080156132ad575060015b6132e35760405163a9059cbb60e01b81525f516020614f1b5f395f51905f529063a9059cbb906130cc9084908690600401614af0565b5f816001600160a01b0316836040515f6040518083038185875af1925050503d805f811461332c576040519150601f19603f3d011682016040523d82523d5f602084013e613331565b606091505b5050905080610e9c5760405163a9059cbb60e01b81525f516020614f1b5f395f51905f529063a9059cbb9061131e9085908790600401614af0565b815f03613377575050565b5f516020614f1b5f395f51905f526001600160a01b03168160a001516001600160a01b031603613498578160085f8282546133b29190614949565b925050819055505f6133c78260a00151613f20565b90505f6133d330610ccb565b6002546133e09190614b9e565b9050801561135e57806133ff6b204fce5e3e2502611000000086614cd3565b6134099190614b7f565b6006838154811061341c5761341c614992565b905f5260205f2090600202016001015f8282546134399190614949565b925050819055505f516020614f3b5f395f51905f528360a0015130866006868154811061346857613468614992565b905f5260205f209060020201600101544260405161348a959493929190614abf565b60405180910390a150505050565b60a0810151604051632a8ddb2f60e01b81525f915f516020614ebb5f395f51905f5291632a8ddb2f916134e0915f516020614f1b5f395f51905f529190601290600401614bc9565b6040805180830381865afa1580156134fa573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061351e9190614c35565b9150505f8260a001516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161355291906145f5565b602060405180830381865afa15801561356d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613591919061491e565b9050600f60099054906101000a90046001600160a01b03166001600160a01b0316635a9ac7068330876135c78860a00151613eed565b6040518563ffffffff1660e01b81526004016135e69493929190614c62565b5f604051808303815f87803b1580156135fd575f5ffd5b505af192505050801561360e575060015b1561135e5760a08301516040516370a0823160e01b81525f916001600160a01b0316906370a08231906136459030906004016145f5565b602060405180830381865afa158015613660573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613684919061491e565b90505f6136918383614b9e565b905080156115f3575f6136a78660a00151613f20565b90505f6136b330610ccb565b6002546136c09190614b9e565b9050801561377357806136df6b204fce5e3e2502611000000085614cd3565b6136e99190614b7f565b600683815481106136fc576136fc614992565b905f5260205f2090600202016001015f8282546137199190614949565b925050819055505f516020614f3b5f395f51905f528760a0015130856006868154811061374857613748614992565b905f5260205f209060020201600101544260405161376a959493929190614abf565b60405180910390a15b5050505050505050565b815f03613788575050565b60068101545f81900361379a57505050565b60048201546001600160a01b03165f81158015906137ce57506001600160a01b0382165f516020614f1b5f395f51905f5214155b9050848115613add57604051632a8ddb2f60e01b81525f905f516020614ebb5f395f51905f5290632a8ddb2f9061381b905f516020614f1b5f395f51905f52908890601290600401614bc9565b6040805180830381865afa158015613835573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138599190614c35565b9150506001600160a01b0381166138735750505050505050565b6040516370a0823160e01b81525f906001600160a01b038616906370a08231906138a19030906004016145f5565b602060405180830381865afa1580156138bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138e0919061491e565b600f5460405163095ea7b360e01b81529192505f516020614f1b5f395f51905f529163095ea7b39161392891600160481b9091046001600160a01b0316908c90600401614af0565b6020604051808303815f875af1158015613944573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139689190614b09565b506040805160028082526060820183525f926020830190803683370190505090505f516020614f1b5f395f51905f52815f815181106139a9576139a9614992565b60200260200101906001600160a01b031690816001600160a01b03168152505085816001815181106139dd576139dd614992565b6001600160a01b039283166020918202929092010152600f54604051637e18437960e01b8152600160481b90910490911690637e18437990613a2990869030908e908790600401614c62565b5f604051808303815f87803b158015613a40575f5ffd5b505af1925050508015613a51575060015b613a6057505050505050505050565b6040516370a0823160e01b815282906001600160a01b038816906370a0823190613a8e9030906004016145f5565b602060405180830381865afa158015613aa9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613acd919061491e565b613ad79190614b9e565b93505050505b5f82613af6575f516020614f1b5f395f51905f52613af8565b835b604051632a8ddb2f60e01b81529091505f905f516020614ebb5f395f51905f5290632a8ddb2f90613b329030908690601290600401614bc9565b6040805180830381865afa158015613b4c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b709190614c35565b9150506001600160a01b038116613b8b575050505050505050565b600f54613bab903090600160481b90046001600160a01b03165f196113e3565b8315613c2f57600f5460405163095ea7b360e01b81526001600160a01b038085169263095ea7b392613bed92600160481b909204909116908790600401614af0565b6020604051808303815f875af1158015613c09573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c2d9190614b09565b505b600f5460405163863f15cd60e01b81526001600160a01b0383811660048301523060248301528481166044830152606482018990526084820186905261dead60a4830152600160481b9092049091169063863f15cd9060c4015f604051808303815f87803b158015613c9f575f5ffd5b505af1925050508015613cb0575060015b15613773575f6018885f015481548110613ccc57613ccc614992565b905f5260205f209060070201600601819055505050505050505050565b5f8080808085604001516002811115613d0457613d04614647565b03613d2a57613d1c8660400151868860c00151614018565b909450925060019050613db0565b600185604001516002811115613d4257613d42614647565b148015613d50575085606001515b15613d6857613d1c8660400151868860c00151614018565b600285604001516002811115613d8057613d80614647565b148015613d8e575085608001515b15613db057613da68660400151868860c00151614018565b9094509250600190505b80613dc4575f5f5f93509350935050613e1c565b5f8660a00151118015613dd657505f84115b15613e07576127108660a0015185613dee9190614cd3565b613df89190614b7f565b9150613e048285614b9e565b93505b613e1a865f0151876020015186886140b5565b505b9250925092565b5f5f5f846001600160a01b0316866001600160a01b031603613e6657613e4886611364565b613e5a57613e5586610bd9565b613e5c565b5f5b92505f9150613ea5565b613e6f86611364565b613e8157613e7c86610bd9565b613e83565b5f5b9250613e8e85611364565b613ea057613e9b85610bd9565b613ea2565b5f5b91505b613eae84611753565b6007546001600160a01b039586165f90815260096020526040808220839055988716815288812082905596909516865295909420929092559390929150565b6040516377a9efe360e11b81526060905f516020614ebb5f395f51905f529063ef53dfc690612f979085906004016145f5565b5f805b600654811015613f7657826001600160a01b031660068281548110613f4a57613f4a614992565b5f9182526020909120600290910201546001600160a01b031603613f6e5792915050565b600101613f23565b50604080518082019091526001600160a01b0383811682525f6020830181815260068054600180820183559382905294517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f600290960295860180546001600160a01b0319169190951617909355517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4090930192909255546108099190614b9e565b6060820151604051632b8d28ef60e21b8152600481018590526024810191909152604481018290526001606482015261271060848201525f9081905f516020614ebb5f395f51905f529063ae34a3bc9060a4016040805180830381865afa158015614085573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140a99190614b5d565b91509150935093915050565b805f01517f4561d7b5bc749427362f16999e4266d5e838624dc76c7915a80597b4303f910682602001518360400151878787426040516140fa96959493929190614e2f565b60405180910390a25f8160200151600581111561411957614119614647565b0361412d5761412884836141f4565b61135e565b60038160200151600581111561414557614145614647565b0361415457614128848361423b565b60028160200151600581111561416c5761416c614647565b0361417c576141288483836142fb565b60018160200151600581111561419457614194614647565b036141a4576141288483836143a8565b6004816020015160058111156141bc576141bc614647565b036141cc57614128848383614458565b6005816020015160058111156141e4576141e4614647565b0361135e5761135e8483836144e7565b8060195f8282546142059190614949565b90915550506040515f516020614e9b5f395f51905f5290614229908390429061495c565b60405180910390a161171b828261171f565b6142468230836124a7565b5f61425030610ccb565b60025461425d9190614b9e565b905080156142b4578061427c6b204fce5e3e2502611000000084614cd3565b6142869190614b7f565b60075f8282546142969190614949565b9250508190555081601b5f8282546142ae9190614949565b90915550505b6007546040805184815260208101929092524282820152517f4aa5b1e7e0aa0cb24a794cb0410918d48c70726a1891006de7d83adf6ec039209181900360600190a1505050565b60808101516001600160a01b03165f9081526013602052604090205460ff166143455760808101516001600160a01b03165f908152601360205260409020805460ff191660011790555b8060e00151156143995761435a8330846124a7565b816018825f01518154811061437157614371614992565b905f5260205f2090600702016006015f82825461438e9190614949565b90915550610e9c9050565b610e9c838260800151846124a7565b600d805460ff191660011790556143c08330846124a7565b816018825f0151815481106143d7576143d7614992565b905f5260205f2090600702016006015f8282546143f49190614949565b9250508190555081601a5f82825461440c9190614949565b90915550508051608082015160a08301516040515f516020614e7b5f395f51905f529361444193879391925f92904290614cea565b60405180910390a15050600d805460ff1916905550565b600d805460ff191660011790556144708330846124a7565b816018825f01518154811061448757614487614992565b905f5260205f2090600702016006015f8282546144a49190614949565b9250508190555081601c5f8282546144bc9190614949565b909155505060a08101516040515f516020614edb5f395f51905f52916144419185915f914290614d1e565b600d805460ff191660011790556144ff8330846124a7565b816018825f01518154811061451657614516614992565b905f5260205f2090600702016006015f8282546145339190614949565b9250508190555081601d5f82825461454b9190614949565b9091555050600d805460ff19169055505050565b602081525f82518060208401525f5b8181101561458b576020818601810151604086840101520161456e565b505f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b0381168114610b05575f5ffd5b5f5f604083850312156145cf575f5ffd5b82356145da816145aa565b946020939093013593505050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b5f5f5f6060848603121561461b575f5ffd5b8335614626816145aa565b92506020840135614636816145aa565b929592945050506040919091013590565b634e487b7160e01b5f52602160045260245ffd5b6006811061466b5761466b614647565b9052565b6003811061466b5761466b614647565b602080825282518282018190525f918401906040840190835b818110156147425783518051845260208101516146b8602086018261465b565b5060408101516146cb604086018261466f565b506060810151606085015260018060a01b03608082015116608085015260018060a01b0360a08201511660a085015260c081015161470c60c08601826145e8565b5060e081015161472060e086018215159052565b5061010090810151908401526020939093019261012090920191600101614698565b509095945050505050565b5f6020828403121561475d575f5ffd5b5035919050565b5f5f60408385031215614775575f5ffd5b823591506020830135614787816145aa565b809150509250929050565b5f602082840312156147a2575f5ffd5b81356111f3816145aa565b602080825282518282018190525f918401906040840190835b818110156147425783518352602093840193909201916001016147c6565b602080825282518282018190525f918401906040840190835b8181101561474257835180516001600160a01b0316845260209081015181850152909301926040909201916001016147fd565b8981526101208101614845602083018b61465b565b614852604083018a61466f565b60608201979097526001600160a01b03958616608082015293851660a08501529190931660c083015291151560e082015261010001529392505050565b5f5f604083850312156148a0575f5ffd5b82356148ab816145aa565b91506020830135614787816145aa565b600181811c908216806148cf57607f821691505b6020821081036148ed57634e487b7160e01b5f52602260045260245ffd5b50919050565b80516148fe816145aa565b919050565b5f60208284031215614913575f5ffd5b81516111f3816145aa565b5f6020828403121561492e575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561080957610809614935565b918252602082015260400190565b6020808252600e908201526d125b9d985b1a59081d185e08125160921b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b60208082526012908201527127b7363c903330b1ba37b93c9037bbb732b960711b604082015260600190565b6001600160a01b031690565b602080825282548282018190525f848152918220906040840190835b8181101561474257835483526001840154614a1b6020850160ff831661465b565b614a2e6040850160ff8360081c1661466f565b5060028401546060840152614a4660038501546149d2565b614a5360808501826145e8565b50614a6160048501546149d2565b614a6e60a08501826145e8565b506005840154614a8a60c085016001600160a01b0383166145e8565b614a9e60e0850160ff8360a01c1615159052565b506006840154610100840152600790930192610120909201916001016149fa565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b6001600160a01b03929092168252602082015260400190565b5f60208284031215614b19575f5ffd5b815180151581146111f3575f5ffd5b6001600160a01b039390931683526020830191909152604082015260600190565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215614b6e575f5ffd5b505080516020909101519092909150565b5f82614b9957634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561080957610809614935565b5f60018201614bc257614bc2614935565b5060010190565b6001600160a01b038481168252831660208083019190915260606040830181905283549083018190525f848152918220906080840190835b81811015614c285783546001600160a01b0316835260019384019360209093019201614c01565b5090979650505050505050565b5f5f60408385031215614c46575f5ffd5b8251614c51816145aa565b6020840151909250614787816145aa565b6001600160a01b03858116825284166020808301919091526040820184905260806060830181905283519083018190525f9184019060a0840190835b81811015614cc55783516001600160a01b0316835260209384019390920191600101614c9e565b509098975050505050505050565b808202811582820484141761080957610809614935565b958652602086019490945260408501929092526001600160a01b03908116606085015216608083015260a082015260c00190565b93845260208401929092526001600160a01b03166040830152606082015260800190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b5f60208284031215614d75575f5ffd5b81516001600160401b03811115614d8a575f5ffd5b8201601f81018413614d9a575f5ffd5b80516001600160401b03811115614db357614db3614b49565b604051600582901b90603f8201601f191681016001600160401b0381118282101715614de157614de1614b49565b604052918252602081840181019290810187841115614dfe575f5ffd5b6020850194505b83851015614e2457614e16856148f3565b815260209485019401614e05565b509695505050505050565b60c08101614e3d828961465b565b614e4a602083018861466f565b6001600160a01b039586166040830152939094166060850152608084019190915260a0909201919091529291505056fe4273856ca27b03e758cdfc9b3b6ca37d494ecb75fbae628757965b75fb104ab6240ac4b1276638a07697a276a1e769aeeef6a875321508eee58718c790a0eb25000000000000000000000000d3397b405a2272f5c27fc673be20579f22f59d6cf7d7115427aac464a6917f7ba3066179fd0c845521f577e53e8e4d4ec97dd4a8799663458a5ef2936f7fa0c99b3336c69c25890f82974f04e811e5bb359186c7000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a27c24cdf2085ca2e96c74f42d25648701f34a19b69bce82381dffcf6d00a8dcad5a164736f6c634300081f000a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000b1ae112d59513618a04fd5e83bd7efba05a3f000000000000000000000000d7b71ca606f9a780d81d6581b887b1c9ad9407720000000000000000000000000000000000000000033b2e3c9fd0803ce80000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000cae394005c9c4c309621c53d53db9ceb701fc8d8000000000000000000000000000b1ae112d59513618a04fd5e83bd7efba05a3f000000000000000000000000d3397b405a2272f5c27fc673be20579f22f59d6c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1ae112d59513618a04fd5e83bd7efba05a3f000000000000000000000000000000000000000002091fb06eec50ca360000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065969656c645800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004594c445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008577f0fb9d709d5bebd808dddd0094fbaec667b4000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008577f0fb9d709d5bebd808dddd0094fbaec667b4000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c450b3c2b89a2dabe5a3ee39ff475134a30d665000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c450b3c2b89a2dabe5a3ee39ff475134a30d66500000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f8db0aba00007681f8faf16a0fda1c9b030b1100000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f8db0aba00007681f8faf16a0fda1c9b030b1100000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f2da3942616880e52e841e5c504b5a9fba23fff000000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f2da3942616880e52e841e5c504b5a9fba23fff00000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000f2da3942616880e52e841e5c504b5a9fba23fff00000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000f2da3942616880e52e841e5c504b5a9fba23fff0000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000008577f0fb9d709d5bebd808dddd0094fbaec667b4000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000008577f0fb9d709d5bebd808dddd0094fbaec667b4000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x60806040526004361061021a575f3560e01c8063014182051461022557806306fdde031461024d578063095ea7b31461026e5780630d3ebcbf1461029d57806313299604146102b3578063138dd4d1146102d457806318160ddd146102e857806322849720146102fc57806323b872dd146103115780632973ef2d14610330578063313ce56714610351578063346847b41461036c578063378dc3dc14610380578063406cf2291461039557806342966c68146103a95780634ada218b146103c85780634f30800d146103e157806358232c94146103f5578063695d69b3146104145780636a2072d414610433578063709df63c1461045f57806370a0823114610480578063715018a61461049f5780637922fc01146104b35780637c8b6f09146104c857806384527bbd146105045780638453ef99146105195780638a8c523c1461052d5780638da5cb5b146105415780639045be581461055557806390b8e5981461058357806395d89b41146105a25780639b165f4e146105b6578063a9059cbb146105d5578063ad826ab6146105f4578063b2ff197314610613578063c5be2bc714610627578063cb78c1631461065b578063ce7b63ed1461066f578063ced72f8714610683578063d89135cd14610697578063dd62ed3e146106ac578063e4f8d62e146106cb578063e5711e8b146106ea578063e6375d3e14610709578063eb50c06114610728578063f2fde38b14610747575f5ffd5b3661022157005b5f5ffd5b348015610230575f5ffd5b5061023a601c5481565b6040519081526020015b60405180910390f35b348015610258575f5ffd5b50610261610766565b604051610244919061455f565b348015610279575f5ffd5b5061028d6102883660046145be565b6107f6565b6040519015158152602001610244565b3480156102a8575f5ffd5b506102b161080f565b005b3480156102be575f5ffd5b506102c7610839565b60405161024491906145f5565b3480156102df575f5ffd5b506102c76108a9565b3480156102f3575f5ffd5b5060025461023a565b348015610307575f5ffd5b5061023a601b5481565b34801561031c575f5ffd5b5061028d61032b366004614609565b6108f0565b34801561033b575f5ffd5b50610344610913565b604051610244919061467f565b34801561035c575f5ffd5b5060405160128152602001610244565b348015610377575f5ffd5b5061023a610a42565b34801561038b575f5ffd5b5061023a600e5481565b3480156103a0575f5ffd5b5061028d610aad565b3480156103b4575f5ffd5b506102b16103c336600461474d565b610abe565b3480156103d3575f5ffd5b50600f5461028d9060ff1681565b3480156103ec575f5ffd5b5060075461023a565b348015610400575f5ffd5b506102b161040f366004614764565b610b08565b34801561041f575f5ffd5b5061023a61042e366004614792565b610bd9565b34801561043e575f5ffd5b5061045261044d366004614792565b610bf8565b60405161024491906147ad565b34801561046a575f5ffd5b50610473610c61565b60405161024491906147e4565b34801561048b575f5ffd5b5061023a61049a366004614792565b610ccb565b3480156104aa575f5ffd5b506102b1610ce5565b3480156104be575f5ffd5b5061023a601d5481565b3480156104d3575f5ffd5b50600f546104ec9061010090046001600160401b031681565b6040516001600160401b039091168152602001610244565b34801561050f575f5ffd5b5061023a601a5481565b348015610524575f5ffd5b506102b1610cf6565b348015610538575f5ffd5b506102b1610d08565b34801561054c575f5ffd5b506102c7610d58565b348015610560575f5ffd5b5061028d61056f366004614792565b600a6020525f908152604090205460ff1681565b34801561058e575f5ffd5b506102b161059d3660046145be565b610d67565b3480156105ad575f5ffd5b50610261610ea1565b3480156105c1575f5ffd5b506102b16105d0366004614792565b610eb0565b3480156105e0575f5ffd5b5061028d6105ef3660046145be565b610edb565b3480156105ff575f5ffd5b506102b161060e366004614764565b610ee8565b34801561061e575f5ffd5b5060165461023a565b348015610632575f5ffd5b5061064661064136600461474d565b610fb1565b60405161024499989796959493929190614830565b348015610666575f5ffd5b5061023a611026565b34801561067a575f5ffd5b5060155461023a565b34801561068e575f5ffd5b5061023a611073565b3480156106a2575f5ffd5b5061023a60195481565b3480156106b7575f5ffd5b5061023a6106c636600461488f565b6110ba565b3480156106d6575f5ffd5b5061023a6106e53660046145be565b6110e4565b3480156106f5575f5ffd5b506102b1610704366004614609565b6111fa565b348015610714575f5ffd5b5061028d610723366004614792565b611364565b348015610733575f5ffd5b506102b1610742366004614792565b611381565b348015610752575f5ffd5b506102b1610761366004614792565b6113a9565b606060038054610775906148bb565b80601f01602080910402602001604051908101604052809291908181526020018280546107a1906148bb565b80156107ec5780601f106107c3576101008083540402835291602001916107ec565b820191905f5260205f20905b8154815290600101906020018083116107cf57829003601f168201915b5050505050905090565b5f336108038185856113e3565b60019150505b92915050565b6108176113f0565b600f54610837903090600160481b90046001600160a01b03165f196113e3565b565b601154604080516336ce6de360e11b815290515f926001600160a01b031691636d9cdbc69160048083019260209291908290030181865afa158015610880573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a49190614903565b905090565b60115460408051637bb8996d60e01b815290515f926001600160a01b031691637bb8996d9160048083019260209291908290030181865afa158015610880573d5f5f3e3d5ffd5b5f336108fd858285611422565b61090885858561146d565b506001949350505050565b60606018805480602002602001604051908101604052809291908181526020015f905b82821015610a39578382905f5260205f209060070201604051806101200160405290815f8201548152602001600182015f9054906101000a900460ff16600581111561098457610984614647565b600581111561099557610995614647565b81526020016001820160019054906101000a900460ff1660028111156109bd576109bd614647565b60028111156109ce576109ce614647565b8152600282015460208083019190915260038301546001600160a01b03908116604084015260048401548116606084015260058401549081166080840152600160a01b900460ff16151560a083015260069092015460c0909101529082526001929092019101610936565b50505050905090565b6011546040805163b5a08dd160e01b815290515f926001600160a01b03169163b5a08dd19160048083019260209291908290030181865afa158015610a89573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a4919061491e565b5f610ab833336116f1565b50600190565b8060195f828254610acf9190614949565b90915550506040515f516020614e9b5f395f51905f5290610af3908390429061495c565b60405180910390a1610b05338261171f565b50565b610b106113f0565b6018548210610b3a5760405162461bcd60e51b8152600401610b319061496a565b60405180910390fd5b6001600160a01b038116610b8f5760405162461bcd60e51b815260206004820152601c60248201527b546f6b656e20616464726573732063616e6e6f74206265207a65726f60201b6044820152606401610b31565b8060188381548110610ba357610ba3614992565b905f5260205f2090600702016004015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b5f610be382611364565b15610bef57505f919050565b61080982611753565b6001600160a01b0381165f908152600c6020908152604091829020805483518184028101840190945280845260609392830182828015610c5557602002820191905f5260205f20905b815481526020019060010190808311610c41575b50505050509050919050565b60606006805480602002602001604051908101604052809291908181526020015f905b82821015610a39575f848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610c84565b6001600160a01b03165f9081526020819052604090205490565b610ced6113f0565b6108375f6117f0565b610cfe6113f0565b6108375f19611841565b610d106113f0565b600f5460ff1615610d3457604051637952fbad60e11b815260040160405180910390fd5b600f805460ff191660011790556040515f516020614efb5f395f51905f52905f90a1565b6005546001600160a01b031690565b60115f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610db7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddb9190614903565b6001600160a01b0316336001600160a01b031614610e0b5760405162461bcd60e51b8152600401610b31906149a6565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610e54576040519150601f19603f3d011682016040523d82523d5f602084013e610e59565b606091505b5050905080610e9c5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610b31565b505050565b606060048054610775906148bb565b610eb86113f0565b6001600160a01b03165f908152601360205260409020805460ff19166001179055565b5f3361080381858561146d565b610ef06113f0565b6018548210610f115760405162461bcd60e51b8152600401610b319061496a565b6001600160a01b038116610f675760405162461bcd60e51b815260206004820152601f60248201527f52656365697665722063616e6e6f74206265207a65726f2061646472657373006044820152606401610b31565b8060188381548110610f7b57610f7b614992565b905f5260205f2090600702016003015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b60188181548110610fc0575f80fd5b5f918252602090912060079091020180546001820154600283015460038401546004850154600586015460069096015494965060ff8085169661010090950481169593946001600160a01b039384169492841693811692600160a01b9091049091169089565b604051625f8d8f60e81b81525f905f516020614ebb5f395f51905f5290635f8d8f0090611058906018906004016149de565b602060405180830381865afa158015610a89573d5f5f3e3d5ffd5b6011546040805163c57981b560e01b815290515f926001600160a01b03169163c57981b59160048083019260209291908290030181865afa158015610a89573d5f5f3e3d5ffd5b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6001600160a01b0382165f908152600c6020526040812054821061110957505f610809565b5f516020614ebb5f395f51905f526001600160a01b031663a89055e584306006868154811061113a5761113a614992565b905f5260205f20906002020160010154600c5f896001600160a01b03166001600160a01b031681526020019081526020015f20878154811061117e5761117e614992565b905f5260205f2001546b204fce5e3e250261100000006040518663ffffffff1660e01b81526004016111b4959493929190614abf565b602060405180830381865afa1580156111cf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f3919061491e565b9392505050565b60115f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561124a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061126e9190614903565b6001600160a01b0316336001600160a01b03161461129e5760405162461bcd60e51b8152600401610b31906149a6565b306001600160a01b038416036112f05760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103932b9b1bab29037bbb7103a37b5b2b760491b6044820152606401610b31565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061131e9085908590600401614af0565b6020604051808303815f875af115801561133a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135e9190614b09565b50505050565b6001600160a01b03165f908152600a602052604090205460ff1690565b6113896113f0565b6001600160a01b03165f908152601360205260409020805460ff19169055565b6113b16113f0565b6001600160a01b0381166113da575f604051631e4fbdf760e01b8152600401610b3191906145f5565b610b05816117f0565b610e9c8383836001612322565b336113f9610d58565b6001600160a01b031614610837573360405163118cdaa760e01b8152600401610b3191906145f5565b5f61142d84846110ba565b90505f1981101561135e578181101561145f57828183604051637dc7a0d960e11b8152600401610b3193929190614b28565b61135e84848484035f612322565b6017805460ff60201b19169055600f546001600160a01b0384165f9081526013602052604090205460ff9182169116811580156114b95750600f5461010090046001600160401b031615155b80156114d55750600f5461010090046001600160401b03164210155b1561150357600f805460ff191660019081179091556040519092505f516020614efb5f395f51905f52905f90a15b61150c846123f4565b156115225761151b858461171f565b5050505050565b8115801561152e575080155b1561154c5760405163bcb8b8fb60e01b815260040160405180910390fd5b5f6115568561242c565b601854909150158061157257506017546301000000900460ff16155b8061157a5750815b8061159c57506001600160a01b0385165f9081526013602052604090205460ff165b806115a95750600d5460ff165b156115fb576017546301000000900460ff161580156115c55750805b156115de576017805463ff000000191663010000001790555b6115e886866116f1565b6115f38686866124a7565b505050505050565b80801561162057506001600160a01b0385165f908152600a602052604090205460ff16155b15611648576001600160a01b0385165f908152600a60205260409020805460ff191660011790555b5f6116538787612504565b90505f8161166a576116658888612579565b61166c565b5f5b90505f61167c89898986866125d4565b60175490915060ff16801561169b5750601754600160201b900460ff16155b80156116a5575082155b156116c7576116b387611841565b6017805460ff60201b1916600160201b1790555b6116d189896116f1565b6116db898961289c565b6116e68989836124a7565b505050505050505050565b60175462010000900460ff161561171b5760105461171b90839083906001600160a01b031661299a565b5050565b6001600160a01b038216611748575f604051634b637e8f60e11b8152600401610b3191906145f5565b61171b825f83612e51565b6007546001600160a01b0382165f90815260096020526040808220549051631d2fa43b60e11b815291925f516020614ebb5f395f51905f5292633a5f4876926117b19287923092906b204fce5e3e2502611000000090600401614abf565b602060405180830381865afa1580156117cc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610809919061491e565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b600d805460ff191660011790556018545f90819081816001600160401b0381111561186e5761186e614b49565b604051908082528060200260200182016040528015611897578160200160208202803683370190505b5090505f826001600160401b038111156118b3576118b3614b49565b6040519080825280602002602001820160405280156118dc578160200160208202803683370190505b5090505f5b83811015611b44575f601882815481106118fd576118fd614992565b905f5260205f209060070201905080600601545f0361191c5750611b3c565b60018082015460ff16600581111561193657611936614647565b148061197057506002600182015460ff16600581111561195857611958614647565b14801561197057506005810154600160a01b900460ff165b8061199357506004600182015460ff16600581111561199157611991614647565b145b806119b657506005600182015460ff1660058111156119b4576119b4614647565b145b15611b3a57600681015460405163059b6d4760e21b81525f9182915f516020614ebb5f395f51905f529163166db51c916119f591908e9060040161495c565b6040805180830381865afa158015611a0f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a339190614b5d565b90925090508115611b0f5781816005600186015460ff166005811115611a5b57611a5b614647565b03611a8457611a6b600285614b7f565b9150611a778285614b9e565b611a819084614949565b90505b6001888781518110611a9857611a98614992565b60200260200101901515908115158152505081878781518110611abd57611abd614992565b6020908102919091010152611ad2828c614949565b9a5089611ade81614bb1565b9a50508060188781548110611af557611af5614992565b905f5260205f209060070201600601819055505050611b37565b8060188581548110611b2357611b23614992565b905f5260205f209060070201600601819055505b50505b505b6001016118e1565b50604051632a8ddb2f60e01b81525f905f516020614ebb5f395f51905f5290632a8ddb2f90611b899030905f516020614f1b5f395f51905f5290601290600401614bc9565b6040805180830381865afa158015611ba3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bc79190614c35565b9150506001600160a01b038116611c0b576040517f34be9cb68ddf4eeebba29ea0e1db420286ea39e4ce7a377e66a7b47a998a6d03905f90a1505050505050612315565b5f5f5f5f5f516020614ebb5f395f51905f526001600160a01b031663166db51c6015548d6040518363ffffffff1660e01b8152600401611c4c92919061495c565b6040805180830381865afa158015611c66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c8a9190614b5d565b60165460405163059b6d4760e21b81529296509093505f516020614ebb5f395f51905f529163166db51c91611cc3918f9060040161495c565b6040805180830381865afa158015611cdd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d019190614b5d565b601593909355601692909255509050611d1a8289614949565b9750611d268189614949565b9750875f03611d3c575050505050505050612315565b600f54600160481b90046001600160a01b0316637e18437984308b611d6082612f64565b6040518563ffffffff1660e01b8152600401611d7f9493929190614c62565b5f604051808303815f87803b158015611d96575f5ffd5b505af1925050508015611da7575060015b611e69575f5b86811015611e2c57858181518110611dc757611dc7614992565b602002602001015115611e2457848181518110611de657611de6614992565b602002602001015160188281548110611e0157611e01614992565b905f5260205f2090600702016006015f828254611e1e9190614949565b90915550505b600101611dad565b508160155f828254611e3e9190614949565b925050819055508060165f828254611e569190614949565b9091555061231598505050505050505050565b6008546040516370a0823160e01b81525f91905f516020614f1b5f395f51905f52906370a0823190611e9f9030906004016145f5565b602060405180830381865afa158015611eba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ede919061491e565b611ee89190614b9e565b9050611ef68184848c612fd8565b611f009082614b9e565b9050611f0c838a614b9e565b9850611f18828a614b9e565b9850805f03611f2f57505050505050505050612315565b5f5b8781101561230a57868181518110611f4b57611f4b614992565b60200260200101511580611f775750858181518110611f6c57611f6c614992565b60200260200101515f145b612302575f8a83888481518110611f9057611f90614992565b6020026020010151611fa29190614cd3565b611fac9190614b7f565b90505f60188381548110611fc257611fc2614992565b5f9182526020909120600790910201905060018082015460ff166005811115611fed57611fed614647565b03612133575f516020614e7b5f395f51905f5288848151811061201257612012614992565b602090810291909101015182546003840154600485015460405161204a94939288926001600160a01b03918216929116904290614cea565b60405180910390a160408051610120810190915281548152600182015461212e9184918490602083019060ff16600581111561208857612088614647565b600581111561209957612099614647565b81526020016001820160019054906101000a900460ff1660028111156120c1576120c1614647565b60028111156120d2576120d2614647565b81526002820154602082015260038201546001600160a01b03908116604083015260048301548116606083015260058301549081166080830152600160a01b900460ff16151560a082015260069091015460c090910152613061565b6122ff565b6002600182015460ff16600581111561214e5761214e614647565b14801561216657506005810154600160a01b900460ff165b1561218457600381015461212e9083906001600160a01b031661324e565b6004600182015460ff16600581111561219f5761219f614647565b036122d5575f516020614edb5f395f51905f528884815181106121c4576121c4614992565b602090810291909101015160048301546040516121f1929186916001600160a01b03909116904290614d1e565b60405180910390a160408051610120810190915281548152600182015461212e9184918490602083019060ff16600581111561222f5761222f614647565b600581111561224057612240614647565b81526020016001820160019054906101000a900460ff16600281111561226857612268614647565b600281111561227957612279614647565b81526002820154602082015260038201546001600160a01b03908116604083015260048301548116606083015260058301549081166080830152600160a01b900460ff16151560a082015260069091015460c09091015261336c565b6005600182015460ff1660058111156122f0576122f0614647565b036122ff576122ff828261377d565b50505b600101611f31565b505050505050505050505b50600d805460ff19169055565b6001600160a01b03841661234b575f60405163e602df0560e01b8152600401610b3191906145f5565b6001600160a01b038316612374575f604051634a1406b160e11b8152600401610b3191906145f5565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561135e57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516123e691815260200190565b60405180910390a350505050565b5f6001600160a01b038216158061241557506103696001600160a01b038316145b806108095750506001600160a01b031661dead1490565b604051630d5c7b5d60e41b81526001600160a01b03821660048201523060248201525f905f516020614ebb5f395f51905f529063d5c7b5d090604401602060405180830381865afa158015612483573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108099190614b09565b6001600160a01b0383166124d0575f604051634b637e8f60e11b8152600401610b3191906145f5565b6001600160a01b0382166124f9575f60405163ec442f0560e01b8152600401610b3191906145f5565b610e9c838383612e51565b604051636468b51760e01b81525f905f516020614ebb5f395f51905f5290636468b5179061253a90869086903090600401614d42565b602060405180830381865afa158015612555573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f39190614b09565b5f6125838361242c565b801561259357506125938261242c565b156125a057506001610809565b60405163154b004960e31b81525f516020614ebb5f395f51905f529063aa5802489061253a90869086903090600401614d42565b6040805160e0810182525f60a0820181905260c082018190526001600160a01b03888116835287166020830152918101859052831515606082015282151560808201526017548291829182919060ff16801561264057505f6126346108a9565b6001600160a01b031614155b156126535761264d610a42565b60a08201525b61265b611073565b60c082015260188054604080516020808402820181019092528281525f9390929091849084015b82821015612785578382905f5260205f209060070201604051806101200160405290815f8201548152602001600182015f9054906101000a900460ff1660058111156126d0576126d0614647565b60058111156126e1576126e1614647565b81526020016001820160019054906101000a900460ff16600281111561270957612709614647565b600281111561271a5761271a614647565b8152600282015460208083019190915260038301546001600160a01b03908116604084015260048401548116606084015260058401549081166080840152600160a01b900460ff16151560a083015260069092015460c0909101529082526001929092019101612682565b505082519293505f9150505b818110156127f9575f5f5f6127bf878786815181106127b2576127b2614992565b6020026020010151613ce9565b919450925090506127d0838b614949565b99506127dc828a614949565b98506127e88189614949565b975050600190920191506127919050565b5084156128445760175460ff1615612832576128168c30876124a7565b8460155f8282546128279190614949565b909155506128449050565b6128448c61283e610839565b876124a7565b831561286c576128558c30866124a7565b8360165f8282546128669190614949565b90915550505b8385612878888d614b9e565b6128829190614b9e565b61288c9190614b9e565b9c9b505050505050505050505050565b601754610100900460ff166128af575050565b6010545f90819081906128ce90869086906001600160a01b0316613e23565b600754604080516001600160a01b03808c1682528a166020820152908101859052606081018490526080810183905260a08101919091524260c082015292955090935091507f7f2255e92a9403cf8dd4b9f679ad1f5f5ce9226dd19b0faf14c84bace34d235b9060e00160405180910390a1821561295e5761294f8561242c565b61295e5761295e3086856124a7565b811561297c5761296d8461242c565b61297c5761297c3085846124a7565b801561151b5760105461151b9030906001600160a01b0316836124a7565b5f5b60065481101561135e575b6001600160a01b0384165f908152600c60205260409020548110612a18576001600160a01b0384165f908152600c6020526040902060068054839081106129f0576129f0614992565b5f918252602080832060016002909302018201548454928301855593835290912001556129a7565b6001600160a01b0383165f908152600c60205260409020548110612a89576001600160a01b0383165f908152600c602052604090206006805483908110612a6157612a61614992565b5f91825260208083206001600290930201820154845492830185559383529091200155612a18565b6001600160a01b0382165f908152600c60205260409020548110612afa576001600160a01b0382165f908152600c602052604090206006805483908110612ad257612ad2614992565b5f91825260208083206001600290930201820154845492830185559383529091200155612a89565b5f612b0485611364565b612b1757612b1285836110e4565b612b19565b5f5b90505f6001600160a01b0386811690861614612b5057612b3885611364565b612b4b57612b4685846110e4565b612b4d565b5f5b90505b6040805160028082526060820183525f9260208301908036833750506040805160028082526060820183529394505f93909250906020830190803683370190505090505f8415612bf25784838281518110612bad57612bad614992565b60200260200101818152505088828281518110612bcc57612bcc614992565b6001600160a01b039092166020928302919091019091015280612bee81614bb1565b9150505b8315612c505783838281518110612c0b57612c0b614992565b60200260200101818152505087828281518110612c2a57612c2a614992565b6001600160a01b039092166020928302919091019091015280612c4c81614bb1565b9150505b5f5b81811015612e3f575f848281518110612c6d57612c6d614992565b60200260200101511115612e375760068781548110612c8e57612c8e614992565b5f91825260209091206002909102015483516001600160a01b039091169063a9059cbb90859084908110612cc457612cc4614992565b6020026020010151868481518110612cde57612cde614992565b60200260200101516040518363ffffffff1660e01b8152600401612d03929190614af0565b6020604051808303815f875af1925050508015612d3d575060408051601f3d908101601f19168201909252612d3a91810190614b09565b60015b15612e3757505f516020614f1b5f395f51905f526001600160a01b031660068881548110612d6d57612d6d614992565b5f9182526020909120600290910201546001600160a01b031603612dbb57838181518110612d9d57612d9d614992565b602002602001015160085f828254612db59190614b9e565b90915550505b60068781548110612dce57612dce614992565b905f5260205f20906002020160010154600c5f858481518110612df357612df3614992565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208881548110612e2b57612e2b614992565b5f918252602090912001555b600101612c52565b50506001909401935061299c92505050565b6001600160a01b038316612e7b578060025f828254612e709190614949565b90915550612ed89050565b6001600160a01b0383165f9081526020819052604090205481811015612eba5783818360405163391434e360e21b8152600401610b3193929190614b28565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216612ef457600280548290039055612f12565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612f5791815260200190565b60405180910390a3505050565b6040516343d7ef9f60e11b81526060905f516020614ebb5f395f51905f52906387afdf3e90612f979085906004016145f5565b5f60405180830381865afa158015612fb1573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108099190810190614d65565b5f8082612fe58688614cd3565b612fef9190614b7f565b905080156130085761300881613003610839565b61324e565b5f836130148689614cd3565b61301e9190614b7f565b9050801561304c575f61302f6108a9565b90506001600160a01b0381161561304a5761304a828261324e565b505b6130568183614949565b979650505050505050565b815f0361306c575050565b5f516020614f1b5f395f51905f526001600160a01b03168160a001516001600160a01b03160361310c57608081015160405163a9059cbb60e01b81525f516020614f1b5f395f51905f529163a9059cbb916130cc91908690600401614af0565b6020604051808303815f875af11580156130e8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e9c9190614b09565b60a0810151604051632a8ddb2f60e01b81525f915f516020614ebb5f395f51905f5291632a8ddb2f91613154915f516020614f1b5f395f51905f529190601290600401614bc9565b6040805180830381865afa15801561316e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131929190614c35565b915050600f60099054906101000a90046001600160a01b03166001600160a01b0316635a9ac706828460800151866131cd8760a00151613eed565b6040518563ffffffff1660e01b81526004016131ec9493929190614c62565b5f604051808303815f87803b158015613203575f5ffd5b505af1925050508015613214575060015b610e9c57608082015160405163a9059cbb60e01b81525f516020614f1b5f395f51905f529163a9059cbb9161131e91908790600401614af0565b815f03613259575050565b604051632e1a7d4d60e01b8152600481018390525f516020614f1b5f395f51905f5290632e1a7d4d906024015f604051808303815f87803b15801561329c575f5ffd5b505af19250505080156132ad575060015b6132e35760405163a9059cbb60e01b81525f516020614f1b5f395f51905f529063a9059cbb906130cc9084908690600401614af0565b5f816001600160a01b0316836040515f6040518083038185875af1925050503d805f811461332c576040519150601f19603f3d011682016040523d82523d5f602084013e613331565b606091505b5050905080610e9c5760405163a9059cbb60e01b81525f516020614f1b5f395f51905f529063a9059cbb9061131e9085908790600401614af0565b815f03613377575050565b5f516020614f1b5f395f51905f526001600160a01b03168160a001516001600160a01b031603613498578160085f8282546133b29190614949565b925050819055505f6133c78260a00151613f20565b90505f6133d330610ccb565b6002546133e09190614b9e565b9050801561135e57806133ff6b204fce5e3e2502611000000086614cd3565b6134099190614b7f565b6006838154811061341c5761341c614992565b905f5260205f2090600202016001015f8282546134399190614949565b925050819055505f516020614f3b5f395f51905f528360a0015130866006868154811061346857613468614992565b905f5260205f209060020201600101544260405161348a959493929190614abf565b60405180910390a150505050565b60a0810151604051632a8ddb2f60e01b81525f915f516020614ebb5f395f51905f5291632a8ddb2f916134e0915f516020614f1b5f395f51905f529190601290600401614bc9565b6040805180830381865afa1580156134fa573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061351e9190614c35565b9150505f8260a001516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161355291906145f5565b602060405180830381865afa15801561356d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613591919061491e565b9050600f60099054906101000a90046001600160a01b03166001600160a01b0316635a9ac7068330876135c78860a00151613eed565b6040518563ffffffff1660e01b81526004016135e69493929190614c62565b5f604051808303815f87803b1580156135fd575f5ffd5b505af192505050801561360e575060015b1561135e5760a08301516040516370a0823160e01b81525f916001600160a01b0316906370a08231906136459030906004016145f5565b602060405180830381865afa158015613660573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613684919061491e565b90505f6136918383614b9e565b905080156115f3575f6136a78660a00151613f20565b90505f6136b330610ccb565b6002546136c09190614b9e565b9050801561377357806136df6b204fce5e3e2502611000000085614cd3565b6136e99190614b7f565b600683815481106136fc576136fc614992565b905f5260205f2090600202016001015f8282546137199190614949565b925050819055505f516020614f3b5f395f51905f528760a0015130856006868154811061374857613748614992565b905f5260205f209060020201600101544260405161376a959493929190614abf565b60405180910390a15b5050505050505050565b815f03613788575050565b60068101545f81900361379a57505050565b60048201546001600160a01b03165f81158015906137ce57506001600160a01b0382165f516020614f1b5f395f51905f5214155b9050848115613add57604051632a8ddb2f60e01b81525f905f516020614ebb5f395f51905f5290632a8ddb2f9061381b905f516020614f1b5f395f51905f52908890601290600401614bc9565b6040805180830381865afa158015613835573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138599190614c35565b9150506001600160a01b0381166138735750505050505050565b6040516370a0823160e01b81525f906001600160a01b038616906370a08231906138a19030906004016145f5565b602060405180830381865afa1580156138bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138e0919061491e565b600f5460405163095ea7b360e01b81529192505f516020614f1b5f395f51905f529163095ea7b39161392891600160481b9091046001600160a01b0316908c90600401614af0565b6020604051808303815f875af1158015613944573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139689190614b09565b506040805160028082526060820183525f926020830190803683370190505090505f516020614f1b5f395f51905f52815f815181106139a9576139a9614992565b60200260200101906001600160a01b031690816001600160a01b03168152505085816001815181106139dd576139dd614992565b6001600160a01b039283166020918202929092010152600f54604051637e18437960e01b8152600160481b90910490911690637e18437990613a2990869030908e908790600401614c62565b5f604051808303815f87803b158015613a40575f5ffd5b505af1925050508015613a51575060015b613a6057505050505050505050565b6040516370a0823160e01b815282906001600160a01b038816906370a0823190613a8e9030906004016145f5565b602060405180830381865afa158015613aa9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613acd919061491e565b613ad79190614b9e565b93505050505b5f82613af6575f516020614f1b5f395f51905f52613af8565b835b604051632a8ddb2f60e01b81529091505f905f516020614ebb5f395f51905f5290632a8ddb2f90613b329030908690601290600401614bc9565b6040805180830381865afa158015613b4c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b709190614c35565b9150506001600160a01b038116613b8b575050505050505050565b600f54613bab903090600160481b90046001600160a01b03165f196113e3565b8315613c2f57600f5460405163095ea7b360e01b81526001600160a01b038085169263095ea7b392613bed92600160481b909204909116908790600401614af0565b6020604051808303815f875af1158015613c09573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c2d9190614b09565b505b600f5460405163863f15cd60e01b81526001600160a01b0383811660048301523060248301528481166044830152606482018990526084820186905261dead60a4830152600160481b9092049091169063863f15cd9060c4015f604051808303815f87803b158015613c9f575f5ffd5b505af1925050508015613cb0575060015b15613773575f6018885f015481548110613ccc57613ccc614992565b905f5260205f209060070201600601819055505050505050505050565b5f8080808085604001516002811115613d0457613d04614647565b03613d2a57613d1c8660400151868860c00151614018565b909450925060019050613db0565b600185604001516002811115613d4257613d42614647565b148015613d50575085606001515b15613d6857613d1c8660400151868860c00151614018565b600285604001516002811115613d8057613d80614647565b148015613d8e575085608001515b15613db057613da68660400151868860c00151614018565b9094509250600190505b80613dc4575f5f5f93509350935050613e1c565b5f8660a00151118015613dd657505f84115b15613e07576127108660a0015185613dee9190614cd3565b613df89190614b7f565b9150613e048285614b9e565b93505b613e1a865f0151876020015186886140b5565b505b9250925092565b5f5f5f846001600160a01b0316866001600160a01b031603613e6657613e4886611364565b613e5a57613e5586610bd9565b613e5c565b5f5b92505f9150613ea5565b613e6f86611364565b613e8157613e7c86610bd9565b613e83565b5f5b9250613e8e85611364565b613ea057613e9b85610bd9565b613ea2565b5f5b91505b613eae84611753565b6007546001600160a01b039586165f90815260096020526040808220839055988716815288812082905596909516865295909420929092559390929150565b6040516377a9efe360e11b81526060905f516020614ebb5f395f51905f529063ef53dfc690612f979085906004016145f5565b5f805b600654811015613f7657826001600160a01b031660068281548110613f4a57613f4a614992565b5f9182526020909120600290910201546001600160a01b031603613f6e5792915050565b600101613f23565b50604080518082019091526001600160a01b0383811682525f6020830181815260068054600180820183559382905294517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f600290960295860180546001600160a01b0319169190951617909355517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4090930192909255546108099190614b9e565b6060820151604051632b8d28ef60e21b8152600481018590526024810191909152604481018290526001606482015261271060848201525f9081905f516020614ebb5f395f51905f529063ae34a3bc9060a4016040805180830381865afa158015614085573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140a99190614b5d565b91509150935093915050565b805f01517f4561d7b5bc749427362f16999e4266d5e838624dc76c7915a80597b4303f910682602001518360400151878787426040516140fa96959493929190614e2f565b60405180910390a25f8160200151600581111561411957614119614647565b0361412d5761412884836141f4565b61135e565b60038160200151600581111561414557614145614647565b0361415457614128848361423b565b60028160200151600581111561416c5761416c614647565b0361417c576141288483836142fb565b60018160200151600581111561419457614194614647565b036141a4576141288483836143a8565b6004816020015160058111156141bc576141bc614647565b036141cc57614128848383614458565b6005816020015160058111156141e4576141e4614647565b0361135e5761135e8483836144e7565b8060195f8282546142059190614949565b90915550506040515f516020614e9b5f395f51905f5290614229908390429061495c565b60405180910390a161171b828261171f565b6142468230836124a7565b5f61425030610ccb565b60025461425d9190614b9e565b905080156142b4578061427c6b204fce5e3e2502611000000084614cd3565b6142869190614b7f565b60075f8282546142969190614949565b9250508190555081601b5f8282546142ae9190614949565b90915550505b6007546040805184815260208101929092524282820152517f4aa5b1e7e0aa0cb24a794cb0410918d48c70726a1891006de7d83adf6ec039209181900360600190a1505050565b60808101516001600160a01b03165f9081526013602052604090205460ff166143455760808101516001600160a01b03165f908152601360205260409020805460ff191660011790555b8060e00151156143995761435a8330846124a7565b816018825f01518154811061437157614371614992565b905f5260205f2090600702016006015f82825461438e9190614949565b90915550610e9c9050565b610e9c838260800151846124a7565b600d805460ff191660011790556143c08330846124a7565b816018825f0151815481106143d7576143d7614992565b905f5260205f2090600702016006015f8282546143f49190614949565b9250508190555081601a5f82825461440c9190614949565b90915550508051608082015160a08301516040515f516020614e7b5f395f51905f529361444193879391925f92904290614cea565b60405180910390a15050600d805460ff1916905550565b600d805460ff191660011790556144708330846124a7565b816018825f01518154811061448757614487614992565b905f5260205f2090600702016006015f8282546144a49190614949565b9250508190555081601c5f8282546144bc9190614949565b909155505060a08101516040515f516020614edb5f395f51905f52916144419185915f914290614d1e565b600d805460ff191660011790556144ff8330846124a7565b816018825f01518154811061451657614516614992565b905f5260205f2090600702016006015f8282546145339190614949565b9250508190555081601d5f82825461454b9190614949565b9091555050600d805460ff19169055505050565b602081525f82518060208401525f5b8181101561458b576020818601810151604086840101520161456e565b505f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b0381168114610b05575f5ffd5b5f5f604083850312156145cf575f5ffd5b82356145da816145aa565b946020939093013593505050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b5f5f5f6060848603121561461b575f5ffd5b8335614626816145aa565b92506020840135614636816145aa565b929592945050506040919091013590565b634e487b7160e01b5f52602160045260245ffd5b6006811061466b5761466b614647565b9052565b6003811061466b5761466b614647565b602080825282518282018190525f918401906040840190835b818110156147425783518051845260208101516146b8602086018261465b565b5060408101516146cb604086018261466f565b506060810151606085015260018060a01b03608082015116608085015260018060a01b0360a08201511660a085015260c081015161470c60c08601826145e8565b5060e081015161472060e086018215159052565b5061010090810151908401526020939093019261012090920191600101614698565b509095945050505050565b5f6020828403121561475d575f5ffd5b5035919050565b5f5f60408385031215614775575f5ffd5b823591506020830135614787816145aa565b809150509250929050565b5f602082840312156147a2575f5ffd5b81356111f3816145aa565b602080825282518282018190525f918401906040840190835b818110156147425783518352602093840193909201916001016147c6565b602080825282518282018190525f918401906040840190835b8181101561474257835180516001600160a01b0316845260209081015181850152909301926040909201916001016147fd565b8981526101208101614845602083018b61465b565b614852604083018a61466f565b60608201979097526001600160a01b03958616608082015293851660a08501529190931660c083015291151560e082015261010001529392505050565b5f5f604083850312156148a0575f5ffd5b82356148ab816145aa565b91506020830135614787816145aa565b600181811c908216806148cf57607f821691505b6020821081036148ed57634e487b7160e01b5f52602260045260245ffd5b50919050565b80516148fe816145aa565b919050565b5f60208284031215614913575f5ffd5b81516111f3816145aa565b5f6020828403121561492e575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561080957610809614935565b918252602082015260400190565b6020808252600e908201526d125b9d985b1a59081d185e08125160921b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b60208082526012908201527127b7363c903330b1ba37b93c9037bbb732b960711b604082015260600190565b6001600160a01b031690565b602080825282548282018190525f848152918220906040840190835b8181101561474257835483526001840154614a1b6020850160ff831661465b565b614a2e6040850160ff8360081c1661466f565b5060028401546060840152614a4660038501546149d2565b614a5360808501826145e8565b50614a6160048501546149d2565b614a6e60a08501826145e8565b506005840154614a8a60c085016001600160a01b0383166145e8565b614a9e60e0850160ff8360a01c1615159052565b506006840154610100840152600790930192610120909201916001016149fa565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b6001600160a01b03929092168252602082015260400190565b5f60208284031215614b19575f5ffd5b815180151581146111f3575f5ffd5b6001600160a01b039390931683526020830191909152604082015260600190565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215614b6e575f5ffd5b505080516020909101519092909150565b5f82614b9957634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561080957610809614935565b5f60018201614bc257614bc2614935565b5060010190565b6001600160a01b038481168252831660208083019190915260606040830181905283549083018190525f848152918220906080840190835b81811015614c285783546001600160a01b0316835260019384019360209093019201614c01565b5090979650505050505050565b5f5f60408385031215614c46575f5ffd5b8251614c51816145aa565b6020840151909250614787816145aa565b6001600160a01b03858116825284166020808301919091526040820184905260806060830181905283519083018190525f9184019060a0840190835b81811015614cc55783516001600160a01b0316835260209384019390920191600101614c9e565b509098975050505050505050565b808202811582820484141761080957610809614935565b958652602086019490945260408501929092526001600160a01b03908116606085015216608083015260a082015260c00190565b93845260208401929092526001600160a01b03166040830152606082015260800190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b5f60208284031215614d75575f5ffd5b81516001600160401b03811115614d8a575f5ffd5b8201601f81018413614d9a575f5ffd5b80516001600160401b03811115614db357614db3614b49565b604051600582901b90603f8201601f191681016001600160401b0381118282101715614de157614de1614b49565b604052918252602081840181019290810187841115614dfe575f5ffd5b6020850194505b83851015614e2457614e16856148f3565b815260209485019401614e05565b509695505050505050565b60c08101614e3d828961465b565b614e4a602083018861466f565b6001600160a01b039586166040830152939094166060850152608084019190915260a0909201919091529291505056fe4273856ca27b03e758cdfc9b3b6ca37d494ecb75fbae628757965b75fb104ab6240ac4b1276638a07697a276a1e769aeeef6a875321508eee58718c790a0eb25000000000000000000000000d3397b405a2272f5c27fc673be20579f22f59d6cf7d7115427aac464a6917f7ba3066179fd0c845521f577e53e8e4d4ec97dd4a8799663458a5ef2936f7fa0c99b3336c69c25890f82974f04e811e5bb359186c7000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a27c24cdf2085ca2e96c74f42d25648701f34a19b69bce82381dffcf6d00a8dcad5a164736f6c634300081f000a