编译器
0.8.25+commit.b61c2a91
文件 1 的 17:Address.sol
pragma solidity ^0.8.20;
library Address {
error AddressInsufficientBalance(address account);
error AddressEmptyCode(address target);
error FailedInnerCall();
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
文件 2 的 17:Context.sol
pragma solidity ^0.8.20;
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;
}
}
文件 3 的 17:ERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./IERC20Metadata.sol";
import {Context} from "./Context.sol";
import {IERC20Errors} from "./draft-IERC6093.sol";
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;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return 18;
}
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
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;
}
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
_totalSupply -= value;
}
} else {
unchecked {
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
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);
}
}
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);
}
}
}
}
文件 4 的 17:ERC20Burnable.sol
pragma solidity ^0.8.20;
import {ERC20} from "./ERC20.sol";
import {Context} from "./Context.sol";
abstract contract ERC20Burnable is Context, ERC20 {
function burn(uint256 value) public virtual {
_burn(_msgSender(), value);
}
function burnFrom(address account, uint256 value) public virtual {
_spendAllowance(account, _msgSender(), value);
_burn(account, value);
}
}
文件 5 的 17:IERC20.sol
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 6 的 17:IERC20Metadata.sol
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 7 的 17:IUniswapV2Factory.sol
pragma solidity >=0.5.0;
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;
}
文件 8 的 17:IUniswapV2Pair.sol
pragma solidity >=0.5.0;
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;
}
文件 9 的 17:IUniswapV2Router01.sol
pragma solidity >=0.6.2;
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);
}
文件 10 的 17:IUniswapV2Router02.sol
pragma solidity >=0.6.2;
import './IUniswapV2Router01.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;
}
文件 11 的 17:Initializable.sol
pragma solidity ^0.8.19;
abstract contract Initializable {
bool private _initialized;
bool private _initializing;
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
文件 12 的 17:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "./Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 13 的 17:Ownable2Step.sol
pragma solidity ^0.8.20;
import {Ownable} from "./Ownable.sol";
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}
文件 14 的 17:SafeERC20Remastered.sol
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {Address} from "./Address.sol";
library SafeERC20Remastered {
using Address for address;
error SafeERC20FailedOperation(address token);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransfer_noRevert(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
文件 15 的 17:Token.sol
pragma solidity 0.8.25;
import {IERC20, ERC20} from "./ERC20.sol";
import {ERC20Burnable} from "./ERC20Burnable.sol";
import {Ownable, Ownable2Step} from "./Ownable2Step.sol";
import {SafeERC20Remastered} from "./SafeERC20Remastered.sol";
import {DividendTrackerFunctions} from "./TokenDividendTracker.sol";
import {Initializable} from "./Initializable.sol";
import "./IUniswapV2Factory.sol";
import "./IUniswapV2Pair.sol";
import "./IUniswapV2Router01.sol";
import "./IUniswapV2Router02.sol";
contract THUG is ERC20, ERC20Burnable, Ownable2Step, DividendTrackerFunctions, Initializable {
using SafeERC20Remastered for IERC20;
uint16 public swapThresholdRatio;
uint256 private _basePending;
uint256 private _rewardsPending;
address public baseAddress;
uint16[3] public baseFees;
uint16[3] public rewardsFees;
mapping (address => bool) public isExcludedFromFees;
uint16[3] public totalFees;
bool private _swapping;
IUniswapV2Router02 public routerV2;
address public pairV2;
mapping (address => bool) public AMMs;
bool public tradingEnabled;
mapping (address => bool) public isExcludedFromTradingRestriction;
error InvalidAmountToRecover(uint256 amount, uint256 maxAmount);
error InvalidToken(address tokenAddress);
error CannotDepositNativeCoins(address account);
error InvalidSwapThresholdRatio(uint16 swapThresholdRatio);
error InvalidTaxRecipientAddress(address account);
error CannotExceedMaxTotalFee(uint16 buyFee, uint16 sellFee, uint16 transferFee);
error InvalidAMM(address AMM);
error TradingAlreadyEnabled();
error TradingNotEnabled();
event SwapThresholdUpdated(uint16 swapThresholdRatio);
event WalletTaxAddressUpdated(uint8 indexed id, address newAddress);
event WalletTaxFeesUpdated(uint8 indexed id, uint16 buyFee, uint16 sellFee, uint16 transferFee);
event WalletTaxSent(uint8 indexed id, address recipient, uint256 amount);
event RewardsFeesUpdated(uint16 buyFee, uint16 sellFee, uint16 transferFee);
event RewardsSent(uint256 amount);
event ExcludeFromFees(address indexed account, bool isExcluded);
event RouterV2Updated(address indexed routerV2);
event AMMUpdated(address indexed AMM, bool isAMM);
event TradingEnabled();
event ExcludeFromTradingRestriction(address indexed account, bool isExcluded);
constructor()
ERC20(unicode"THUG", unicode"THUG")
Ownable(msg.sender)
{
address supplyRecipient = 0x344C8fBE8bC25fe300048F3d6FC599857cB2c821;
updateSwapThreshold(10);
baseAddressSetup(0x8BD814939e53C758102FD12F64859BA72CD93BFf);
baseFeesSetup(310, 330, 0);
_deployDividendTracker(60, 1000000000 * (10 ** decimals()) / 10);
gasForProcessingSetup(300000);
rewardsFeesSetup(100, 100, 0);
_excludeFromDividends(supplyRecipient, true);
_excludeFromDividends(address(this), true);
_excludeFromDividends(address(dividendTracker), true);
excludeFromFees(supplyRecipient, true);
excludeFromFees(address(this), true);
excludeFromTradingRestriction(supplyRecipient, true);
excludeFromTradingRestriction(address(this), true);
_mint(supplyRecipient, 20000000000000 * (10 ** decimals()) / 10);
_transferOwnership(0x344C8fBE8bC25fe300048F3d6FC599857cB2c821);
}
function afterConstructor(address _rewardToken, address _router) initializer external {
_setRewardToken(_rewardToken);
_updateRouterV2(_router);
}
function decimals() public pure override returns (uint8) {
return 9;
}
function recoverToken(uint256 amount) external onlyOwner {
uint256 maxRecoverable = balanceOf(address(this)) - getAllPending();
if (amount > maxRecoverable) revert InvalidAmountToRecover(amount, maxRecoverable);
_update(address(this), msg.sender, amount);
}
function recoverForeignERC20(address tokenAddress, uint256 amount) external onlyOwner {
if (tokenAddress == address(this)) revert InvalidToken(tokenAddress);
IERC20(tokenAddress).safeTransfer(msg.sender, amount);
}
receive() external payable {
if (msg.sender != address(routerV2)) revert CannotDepositNativeCoins(msg.sender);
}
function _swapTokensForCoin(uint256 tokenAmount) private {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = routerV2.WETH();
_approve(address(this), address(routerV2), tokenAmount);
routerV2.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount, 0, path, address(this), block.timestamp);
}
function updateSwapThreshold(uint16 _swapThresholdRatio) public onlyOwner {
if (_swapThresholdRatio == 0 || _swapThresholdRatio > 500) revert InvalidSwapThresholdRatio(_swapThresholdRatio);
swapThresholdRatio = _swapThresholdRatio;
emit SwapThresholdUpdated(_swapThresholdRatio);
}
function getSwapThresholdAmount() public view returns (uint256) {
return balanceOf(pairV2) * swapThresholdRatio / 10000;
}
function getAllPending() public view returns (uint256) {
return 0 + _basePending + _rewardsPending;
}
function baseAddressSetup(address _newAddress) public onlyOwner {
if (_newAddress == address(0)) revert InvalidTaxRecipientAddress(address(0));
baseAddress = _newAddress;
excludeFromFees(_newAddress, true);
emit WalletTaxAddressUpdated(1, _newAddress);
}
function baseFeesSetup(uint16 _buyFee, uint16 _sellFee, uint16 _transferFee) public onlyOwner {
totalFees[0] = totalFees[0] - baseFees[0] + _buyFee;
totalFees[1] = totalFees[1] - baseFees[1] + _sellFee;
totalFees[2] = totalFees[2] - baseFees[2] + _transferFee;
if (totalFees[0] > 2500 || totalFees[1] > 2500 || totalFees[2] > 2500) revert CannotExceedMaxTotalFee(totalFees[0], totalFees[1], totalFees[2]);
baseFees = [_buyFee, _sellFee, _transferFee];
emit WalletTaxFeesUpdated(1, _buyFee, _sellFee, _transferFee);
}
function _swapTokensForOtherRewardTokens(uint256 tokenAmount) private {
address[] memory path = new address[](3);
path[0] = address(this);
path[1] = routerV2.WETH();
path[2] = rewardToken;
_approve(address(this), address(routerV2), tokenAmount);
routerV2.swapExactTokensForTokensSupportingFeeOnTransferTokens(tokenAmount, 0, path, address(this), block.timestamp);
}
function _sendDividends(uint256 tokenAmount) private {
_swapTokensForOtherRewardTokens(tokenAmount);
uint256 dividends = IERC20(rewardToken).balanceOf(address(this));
if (dividends > 0) {
IERC20(rewardToken).safeIncreaseAllowance(address(dividendTracker), dividends);
try dividendTracker.distributeDividends(dividends) {
emit RewardsSent(dividends);
} catch {}
}
}
function excludeFromDividends(address account, bool isExcluded) external onlyOwner {
_excludeFromDividends(account, isExcluded);
}
function _excludeFromDividends(address account, bool isExcluded) internal override {
dividendTracker.excludeFromDividends(account, balanceOf(account), isExcluded);
}
function rewardsFeesSetup(uint16 _buyFee, uint16 _sellFee, uint16 _transferFee) public onlyOwner {
totalFees[0] = totalFees[0] - rewardsFees[0] + _buyFee;
totalFees[1] = totalFees[1] - rewardsFees[1] + _sellFee;
totalFees[2] = totalFees[2] - rewardsFees[2] + _transferFee;
if (totalFees[0] > 2500 || totalFees[1] > 2500 || totalFees[2] > 2500) revert CannotExceedMaxTotalFee(totalFees[0], totalFees[1], totalFees[2]);
rewardsFees = [_buyFee, _sellFee, _transferFee];
emit RewardsFeesUpdated(_buyFee, _sellFee, _transferFee);
}
function excludeFromFees(address account, bool isExcluded) public onlyOwner {
isExcludedFromFees[account] = isExcluded;
emit ExcludeFromFees(account, isExcluded);
}
function _updateRouterV2(address router) private {
routerV2 = IUniswapV2Router02(router);
pairV2 = IUniswapV2Factory(routerV2.factory()).createPair(address(this), routerV2.WETH());
_setAMM(router, true);
_setAMM(pairV2, true);
emit RouterV2Updated(router);
}
function setAMM(address AMM, bool isAMM) external onlyOwner {
if (AMM == pairV2 || AMM == address(routerV2)) revert InvalidAMM(AMM);
_setAMM(AMM, isAMM);
}
function _setAMM(address AMM, bool isAMM) private {
AMMs[AMM] = isAMM;
if (isAMM) {
_excludeFromDividends(AMM, true);
}
emit AMMUpdated(AMM, isAMM);
}
function enableTrading() external onlyOwner {
if (tradingEnabled) revert TradingAlreadyEnabled();
tradingEnabled = true;
emit TradingEnabled();
}
function excludeFromTradingRestriction(address account, bool isExcluded) public onlyOwner {
isExcludedFromTradingRestriction[account] = isExcluded;
emit ExcludeFromTradingRestriction(account, isExcluded);
}
function _update(address from, address to, uint256 amount)
internal
override
{
_beforeTokenUpdate(from, to, amount);
if (from != address(0) && to != address(0)) {
if (!_swapping && amount > 0 && !isExcludedFromFees[from] && !isExcludedFromFees[to]) {
uint256 fees = 0;
uint8 txType = 3;
if (AMMs[from] && !AMMs[to]) {
if (totalFees[0] > 0) txType = 0;
}
else if (AMMs[to] && !AMMs[from]) {
if (totalFees[1] > 0) txType = 1;
}
else if (!AMMs[from] && !AMMs[to]) {
if (totalFees[2] > 0) txType = 2;
}
if (txType < 3) {
fees = amount * totalFees[txType] / 10000;
amount -= fees;
_basePending += fees * baseFees[txType] / totalFees[txType];
_rewardsPending += fees * rewardsFees[txType] / totalFees[txType];
}
if (fees > 0) {
super._update(from, address(this), fees);
}
}
bool canSwap = getAllPending() >= getSwapThresholdAmount() && balanceOf(pairV2) > 0;
if (!_swapping && from != pairV2 && from != address(routerV2) && canSwap) {
_swapping = true;
if (false || _basePending > 0) {
uint256 token2Swap = 0 + _basePending;
bool success = false;
_swapTokensForCoin(token2Swap);
uint256 coinsReceived = address(this).balance;
uint256 basePortion = coinsReceived * _basePending / token2Swap;
if (basePortion > 0) {
(success,) = payable(baseAddress).call{value: basePortion}("");
if (success) {
emit WalletTaxSent(1, baseAddress, basePortion);
}
}
_basePending = 0;
}
if (_rewardsPending > 0 && getNumberOfDividendTokenHolders() > 0) {
_sendDividends(_rewardsPending);
_rewardsPending = 0;
}
_swapping = false;
}
}
super._update(from, to, amount);
_afterTokenUpdate(from, to, amount);
if (from != address(0)) dividendTracker.setBalance(from, balanceOf(from));
if (to != address(0)) dividendTracker.setBalance(to, balanceOf(to));
if (!_swapping) try dividendTracker.process(gasForProcessing) {} catch {}
}
function _beforeTokenUpdate(address from, address to, uint256 amount)
internal
view
{
if (!tradingEnabled) {
if ((AMMs[from] && !AMMs[to] && !isExcludedFromTradingRestriction[to]) || (AMMs[to] && !AMMs[from] && !isExcludedFromTradingRestriction[from])) {
revert TradingNotEnabled();
}
}
}
function _afterTokenUpdate(address from, address to, uint256 amount)
internal
{
}
}
文件 16 的 17:TokenDividendTracker.sol
import {IERC20} from "./IERC20.sol";
import {Ownable, Ownable2Step} from "./Ownable2Step.sol";
import {SafeERC20Remastered} from "./SafeERC20Remastered.sol";
pragma solidity ^0.8.19;
library SafeMathUint {
function toInt256Safe(uint256 a) internal pure returns (int256) {
int256 b = int256(a);
require(b >= 0);
return b;
}
}
library SafeMathInt {
function toUint256Safe(int256 a) internal pure returns (uint256) {
require(a >= 0);
return uint256(a);
}
}
contract TruncatedERC20 {
mapping(address => uint256) private _balances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidSender(address sender);
error ERC20InvalidReceiver(address receiver);
event Transfer(address indexed from, address indexed to, uint256 value);
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return 18;
}
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
function _mint(address account, uint256 amount) internal virtual {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_totalSupply += amount;
unchecked {
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
uint256 accountBalance = _balances[account];
if (accountBalance < amount) {
revert ERC20InsufficientBalance(account, accountBalance, amount);
}
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
}
}
interface DividendPayingTokenInterface {
function dividendOf(address _owner) external view returns (uint256);
event DividendsDistributed(address indexed from, uint256 weiAmount);
event DividendWithdrawn(address indexed to, uint256 weiAmount);
}
interface DividendPayingTokenOptionalInterface {
function withdrawableDividendOf(address _owner) external view returns (uint256);
function withdrawnDividendOf(address _owner) external view returns (uint256);
function accumulativeDividendOf(address _owner) external view returns (uint256);
}
contract DividendPayingToken is TruncatedERC20, DividendPayingTokenInterface, DividendPayingTokenOptionalInterface {
using SafeMathUint for uint256;
using SafeMathInt for int256;
using SafeERC20Remastered for IERC20;
uint256 constant internal magnitude = 2**128;
uint256 internal magnifiedDividendPerShare;
mapping(address => int256) internal magnifiedDividendCorrections;
mapping(address => uint256) internal withdrawnDividends;
uint256 public totalDividendsDistributed;
address public rewardToken;
error DividendTrackerNoEligibleAddresses();
constructor(string memory _name, string memory _symbol) TruncatedERC20(_name, _symbol) {}
function distributeDividends(uint256 amount) public {
if (totalSupply() == 0) {
revert DividendTrackerNoEligibleAddresses();
}
uint256 balBefore = IERC20(rewardToken).balanceOf(address(this));
IERC20(rewardToken).safeTransferFrom(msg.sender, address(this), amount);
uint256 received = IERC20(rewardToken).balanceOf(address(this)) - balBefore;
if (received > 0) {
magnifiedDividendPerShare = magnifiedDividendPerShare + (received * magnitude / totalSupply());
emit DividendsDistributed(msg.sender, received);
totalDividendsDistributed = totalDividendsDistributed + received;
}
}
function _withdrawDividend(address account) internal returns(uint256) {
uint256 withdrawableDividend = withdrawableDividendOf(account);
if (withdrawableDividend > 0) {
withdrawnDividends[account] = withdrawnDividends[account] + withdrawableDividend;
if (IERC20(rewardToken).safeTransfer_noRevert(account, withdrawableDividend)) {
emit DividendWithdrawn(account, withdrawableDividend);
return withdrawableDividend;
} else {
withdrawnDividends[account] = withdrawnDividends[account] - withdrawableDividend;
}
}
return 0;
}
function dividendOf(address account) public view override returns(uint256) {
return withdrawableDividendOf(account);
}
function withdrawableDividendOf(address account) public view override returns(uint256) {
return accumulativeDividendOf(account) - withdrawnDividends[account];
}
function withdrawnDividendOf(address account) public view override returns(uint256) {
return withdrawnDividends[account];
}
function accumulativeDividendOf(address account) public view override returns(uint256) {
return ((magnifiedDividendPerShare * balanceOf(account)).toInt256Safe() + magnifiedDividendCorrections[account]).toUint256Safe() / magnitude;
}
function _mint(address account, uint256 value) internal override {
super._mint(account, value);
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account] - (magnifiedDividendPerShare * value).toInt256Safe();
}
function _burn(address account, uint256 value) internal override {
super._burn(account, value);
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account] + (magnifiedDividendPerShare * value).toInt256Safe();
}
function _setBalance(address account, uint256 newBalance) internal {
uint256 currentBalance = balanceOf(account);
if (newBalance > currentBalance) _mint(account, newBalance - currentBalance);
else if (newBalance < currentBalance) _burn(account, currentBalance - newBalance);
}
}
library IterableMapping {
struct Map {
address[] keys;
mapping(address => uint) values;
mapping(address => uint) indexOf;
mapping(address => bool) inserted;
}
function get(Map storage map, address key) public view returns (uint) {
return map.values[key];
}
function getIndexOfKey(Map storage map, address key) public view returns (int) {
if(!map.inserted[key]) {
return -1;
}
return int(map.indexOf[key]);
}
function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
return map.keys[index];
}
function size(Map storage map) public view returns (uint) {
return map.keys.length;
}
function set(Map storage map, address key, uint val) public {
if (map.inserted[key]) {
map.values[key] = val;
} else {
map.inserted[key] = true;
map.values[key] = val;
map.indexOf[key] = map.keys.length;
map.keys.push(key);
}
}
function remove(Map storage map, address key) public {
if (!map.inserted[key]) {
return;
}
delete map.inserted[key];
delete map.values[key];
uint index = map.indexOf[key];
uint lastIndex = map.keys.length - 1;
address lastKey = map.keys[lastIndex];
map.indexOf[lastKey] = index;
delete map.indexOf[key];
map.keys[index] = lastKey;
map.keys.pop();
}
}
contract DividendTracker is Ownable, DividendPayingToken {
using IterableMapping for IterableMapping.Map;
IterableMapping.Map private tokenHoldersMap;
uint256 public lastProcessedIndex;
mapping(address => bool) public isExcludedFromDividends;
mapping(address => uint256) public lastClaimTimes;
uint256 public claimWait;
uint256 public minimumTokenBalanceForDividends;
error RewardTokenAlreadySet();
error AlreadyExcludedFromDividends(address account);
error AlreadyIncludedInDividends(address account);
error InvalidClaimWait(uint256 claimWait);
event ExcludeFromDividends(address indexed account, bool isExcluded);
event ClaimWaitUpdated(uint256 claimWait);
event ProcessedDividendTracker(uint256 iterations, uint256 claims);
constructor(uint256 _claimWait, uint256 _minimumTokenBalance) DividendPayingToken("DividendTracker", "DividendTracker") Ownable(msg.sender) {
claimWaitSetup(_claimWait);
minimumTokenBalanceForDividends = _minimumTokenBalance;
}
function setRewardToken(address _rewardToken) external onlyOwner {
if (rewardToken != address(0)) revert RewardTokenAlreadySet();
rewardToken = _rewardToken;
}
function excludeFromDividends(address account, uint256 balance, bool isExcluded) external onlyOwner {
if (isExcluded) {
if (isExcludedFromDividends[account]) revert AlreadyExcludedFromDividends(account);
isExcludedFromDividends[account] = true;
_setBalance(account, 0);
tokenHoldersMap.remove(account);
} else {
if (!isExcludedFromDividends[account]) revert AlreadyIncludedInDividends(account);
isExcludedFromDividends[account] = false;
setBalance(account, balance);
}
emit ExcludeFromDividends(account, isExcluded);
}
function claimWaitSetup(uint256 newClaimWait) public onlyOwner {
if (newClaimWait < 60 || newClaimWait > 7 days) revert InvalidClaimWait(newClaimWait);
claimWait = newClaimWait;
emit ClaimWaitUpdated(newClaimWait);
}
function getNumberOfTokenHolders() external view returns (uint256) {
return tokenHoldersMap.keys.length;
}
function getAccountData(address _account) public view returns (
address account,
int256 index,
int256 iterationsUntilProcessed,
uint256 withdrawableDividends,
uint256 totalDividends,
uint256 lastClaimTime,
uint256 nextClaimTime,
uint256 secondsUntilAutoClaimAvailable
)
{
account = _account;
index = tokenHoldersMap.getIndexOfKey(account);
iterationsUntilProcessed = -1;
if (index >= 0) {
if (uint256(index) > lastProcessedIndex) {
iterationsUntilProcessed = index - int256(lastProcessedIndex);
} else {
uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex ? tokenHoldersMap.keys.length - lastProcessedIndex : 0;
iterationsUntilProcessed = index + int256(processesUntilEndOfArray);
}
}
withdrawableDividends = withdrawableDividendOf(account);
totalDividends = accumulativeDividendOf(account);
lastClaimTime = lastClaimTimes[account];
nextClaimTime = lastClaimTime > 0 ? lastClaimTime + claimWait : 0;
secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ? nextClaimTime - block.timestamp : 0;
}
function getAccountDataAtIndex(uint256 index) public view returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256
)
{
if (index >= tokenHoldersMap.size()) return (address(0), -1, -1, 0, 0, 0, 0, 0);
address account = tokenHoldersMap.getKeyAtIndex(index);
return getAccountData(account);
}
function claim(address account) public onlyOwner returns (bool) {
uint256 amount = _withdrawDividend(account);
if (amount > 0) {
lastClaimTimes[account] = block.timestamp;
return true;
}
return false;
}
function _canAutoClaim(uint256 lastClaimTime) private view returns (bool) {
if (block.timestamp < lastClaimTime) return false;
return block.timestamp - lastClaimTime >= claimWait;
}
function setBalance(address account, uint256 newBalance) public onlyOwner {
if (!isExcludedFromDividends[account]) {
if (newBalance >= minimumTokenBalanceForDividends) {
_setBalance(account, newBalance);
tokenHoldersMap.set(account, newBalance);
} else {
_setBalance(account, 0);
tokenHoldersMap.remove(account);
}
}
}
function process(uint256 gas) external onlyOwner returns(uint256 iterations, uint256 claims) {
uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;
if (numberOfTokenHolders == 0) return (0, 0);
uint256 _lastProcessedIndex = lastProcessedIndex;
uint256 gasUsed = 0;
uint256 gasLeft = gasleft();
iterations = 0;
claims = 0;
while (gasUsed < gas && iterations < numberOfTokenHolders) {
_lastProcessedIndex++;
if (_lastProcessedIndex >= tokenHoldersMap.keys.length) _lastProcessedIndex = 0;
address account = tokenHoldersMap.keys[_lastProcessedIndex];
if (_canAutoClaim(lastClaimTimes[account])) {
if (claim(account)) {
claims++;
}
}
iterations++;
uint256 newGasLeft = gasleft();
if (gasLeft > newGasLeft) gasUsed = gasUsed + (gasLeft - newGasLeft);
gasLeft = newGasLeft;
}
lastProcessedIndex = _lastProcessedIndex;
emit ProcessedDividendTracker(iterations, claims);
}
}
abstract contract DividendTrackerFunctions is Ownable2Step {
DividendTracker public dividendTracker;
uint256 public gasForProcessing;
address public rewardToken;
error InvalidGasForProcessing(uint256 gasForProcessing);
event DeployedDividendTracker(address indexed dividendTracker);
event GasForProcessingUpdated(uint256 gasForProcessing);
function _deployDividendTracker(uint256 _claimWait, uint256 _minimumTokenBalance) internal {
dividendTracker = new DividendTracker(_claimWait, _minimumTokenBalance);
emit DeployedDividendTracker(address(dividendTracker));
}
function _setRewardToken(address _rewardToken) internal {
dividendTracker.setRewardToken(_rewardToken);
rewardToken = _rewardToken;
}
function gasForProcessingSetup(uint256 newGasForProcessing) public onlyOwner {
if (newGasForProcessing < 200_000 || newGasForProcessing > 500_000) revert InvalidGasForProcessing(newGasForProcessing);
gasForProcessing = newGasForProcessing;
emit GasForProcessingUpdated(newGasForProcessing);
}
function claimWaitSetup(uint256 claimWait) external onlyOwner {
dividendTracker.claimWaitSetup(claimWait);
}
function _excludeFromDividends(address account, bool isExcluded) internal virtual;
function isExcludedFromDividends(address account) public view returns (bool) {
return dividendTracker.isExcludedFromDividends(account);
}
function claim() external returns(bool) {
return dividendTracker.claim(msg.sender);
}
function getClaimWait() external view returns (uint256) {
return dividendTracker.claimWait();
}
function getTotalDividendsDistributed() external view returns (uint256) {
return dividendTracker.totalDividendsDistributed();
}
function withdrawableDividendOf(address account) public view returns (uint256) {
return dividendTracker.withdrawableDividendOf(account);
}
function dividendTokenBalanceOf(address account) public view returns (uint256) {
return dividendTracker.balanceOf(account);
}
function dividendTokenTotalSupply() public view returns (uint256) {
return dividendTracker.totalSupply();
}
function getAccountDividendsInfo(address account) external view returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256
) {
return dividendTracker.getAccountData(account);
}
function getAccountDividendsInfoAtIndex(uint256 index) external view returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256
) {
return dividendTracker.getAccountDataAtIndex(index);
}
function getLastProcessedIndex() external view returns (uint256) {
return dividendTracker.lastProcessedIndex();
}
function getNumberOfDividendTokenHolders() public view returns (uint256) {
return dividendTracker.getNumberOfTokenHolders();
}
function process(uint256 gas) external returns(uint256 iterations, uint256 claims) {
return dividendTracker.process(gas);
}
}
文件 17 的 17:draft-IERC6093.sol
pragma solidity ^0.8.20;
interface IERC20Errors {
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidSender(address sender);
error ERC20InvalidReceiver(address receiver);
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
error ERC20InvalidApprover(address approver);
error ERC20InvalidSpender(address spender);
}
interface IERC721Errors {
error ERC721InvalidOwner(address owner);
error ERC721NonexistentToken(uint256 tokenId);
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
error ERC721InvalidSender(address sender);
error ERC721InvalidReceiver(address receiver);
error ERC721InsufficientApproval(address operator, uint256 tokenId);
error ERC721InvalidApprover(address approver);
error ERC721InvalidOperator(address operator);
}
interface IERC1155Errors {
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
error ERC1155InvalidSender(address sender);
error ERC1155InvalidReceiver(address receiver);
error ERC1155MissingApprovalForAll(address operator, address owner);
error ERC1155InvalidApprover(address approver);
error ERC1155InvalidOperator(address operator);
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
{
"compilationTarget": {
"Token.sol": "THUG"
},
"evmVersion": "cancun",
"libraries": {
"TokenDividendTracker.sol:IterableMapping": "0x31ee4a53bd2c1c339662dffb973017ef81a6bad5"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"CannotDepositNativeCoins","type":"error"},{"inputs":[{"internalType":"uint16","name":"buyFee","type":"uint16"},{"internalType":"uint16","name":"sellFee","type":"uint16"},{"internalType":"uint16","name":"transferFee","type":"uint16"}],"name":"CannotExceedMaxTotalFee","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"AMM","type":"address"}],"name":"InvalidAMM","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"maxAmount","type":"uint256"}],"name":"InvalidAmountToRecover","type":"error"},{"inputs":[{"internalType":"uint256","name":"gasForProcessing","type":"uint256"}],"name":"InvalidGasForProcessing","type":"error"},{"inputs":[{"internalType":"uint16","name":"swapThresholdRatio","type":"uint16"}],"name":"InvalidSwapThresholdRatio","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"InvalidTaxRecipientAddress","type":"error"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"InvalidToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TradingAlreadyEnabled","type":"error"},{"inputs":[],"name":"TradingNotEnabled","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"AMM","type":"address"},{"indexed":false,"internalType":"bool","name":"isAMM","type":"bool"}],"name":"AMMUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dividendTracker","type":"address"}],"name":"DeployedDividendTracker","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludeFromFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludeFromTradingRestriction","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"gasForProcessing","type":"uint256"}],"name":"GasForProcessingUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"buyFee","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"sellFee","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"transferFee","type":"uint16"}],"name":"RewardsFeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"routerV2","type":"address"}],"name":"RouterV2Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"swapThresholdRatio","type":"uint16"}],"name":"SwapThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"TradingEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"id","type":"uint8"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"WalletTaxAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"id","type":"uint8"},{"indexed":false,"internalType":"uint16","name":"buyFee","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"sellFee","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"transferFee","type":"uint16"}],"name":"WalletTaxFeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"id","type":"uint8"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WalletTaxSent","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"AMMs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_router","type":"address"}],"name":"afterConstructor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"baseAddressSetup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"baseFees","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_buyFee","type":"uint16"},{"internalType":"uint16","name":"_sellFee","type":"uint16"},{"internalType":"uint16","name":"_transferFee","type":"uint16"}],"name":"baseFeesSetup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"claimWait","type":"uint256"}],"name":"claimWaitSetup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"dividendTokenBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dividendTokenTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dividendTracker","outputs":[{"internalType":"contract DividendTracker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"excludeFromDividends","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"excludeFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"excludeFromTradingRestriction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gasForProcessing","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newGasForProcessing","type":"uint256"}],"name":"gasForProcessingSetup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountDividendsInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAccountDividendsInfoAtIndex","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllPending","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getClaimWait","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessedIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumberOfDividendTokenHolders","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapThresholdAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDividendsDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromDividends","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isExcludedFromFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isExcludedFromTradingRestriction","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"process","outputs":[{"internalType":"uint256","name":"iterations","type":"uint256"},{"internalType":"uint256","name":"claims","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverForeignERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardsFees","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_buyFee","type":"uint16"},{"internalType":"uint16","name":"_sellFee","type":"uint16"},{"internalType":"uint16","name":"_transferFee","type":"uint16"}],"name":"rewardsFeesSetup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"routerV2","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"AMM","type":"address"},{"internalType":"bool","name":"isAMM","type":"bool"}],"name":"setAMM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapThresholdRatio","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalFees","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_swapThresholdRatio","type":"uint16"}],"name":"updateSwapThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"withdrawableDividendOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]