ETH Price: $2,512.54 (-0.15%)

Transaction Decoder

Block:
16866164 at Mar-20-2023 03:19:23 AM +UTC
Transaction Fee:
0.002008754882516108 ETH $5.05
Gas Used:
119,993 Gas / 16.740600556 Gwei

Emitted Events:

190 RuffRuff.Transfer( from=[Sender] 0xa84835d0b0f0001539b2f251f134bb3b180082ce, to=0x79bb646AAAf34fF3f74937EAB4B99F5Dd0CC8075, value=9901721799879000 )
191 0xc3da285f8e63082562779cb1de69b27927227fd5.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x000000000000000000000000a84835d0b0f0001539b2f251f134bb3b180082ce, 0x0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000232d90428becee )
192 0xc3da285f8e63082562779cb1de69b27927227fd5.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000079bb646aaaf34ff3f74937eab4b99f5dd0cc8075, 00000000000000000000000000000000000000000000000000232d90428be958 )

Account State Difference:

  Address   Before After State Difference Code
5.26066875737267289 Eth5.260703451514409892 Eth0.000034694141737002
0x9259745C...2C836c743
0xa84835d0...B180082CE
0.890122524582139922 Eth
Nonce: 851
0.888113769699623814 Eth
Nonce: 852
0.002008754882516108
0xC3da285F...927227Fd5

Execution Trace

RuffRuff.transfer( recipient=0x79bb646AAAf34fF3f74937EAB4B99F5Dd0CC8075, amount=9901721799879000 ) => ( True )
  • 0xc3da285f8e63082562779cb1de69b27927227fd5.e30443bc( )
  • 0xc3da285f8e63082562779cb1de69b27927227fd5.e30443bc( )
    /**
     *Submitted for verification at BscScan.com on 2023-03-02
     */
    // SPDX-License-Identifier: Unlicensed
    pragma solidity 0.8.18;
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
        function _msgData() internal view virtual returns (bytes memory) {
            this;
            return msg.data;
        }
    }
    interface IUniswapV2Pair {
        event Approval(
            address indexed owner,
            address indexed spender,
            uint256 value
        );
        event Transfer(address indexed from, address indexed to, uint256 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 (uint256);
        function balanceOf(address owner) external view returns (uint256);
        function allowance(address owner, address spender)
            external
            view
            returns (uint256);
        function approve(address spender, uint256 value) external returns (bool);
        function transfer(address to, uint256 value) external returns (bool);
        function transferFrom(
            address from,
            address to,
            uint256 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 (uint256);
        function permit(
            address owner,
            address spender,
            uint256 value,
            uint256 deadline,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external;
        event Mint(address indexed sender, uint256 amount0, uint256 amount1);
        event Burn(
            address indexed sender,
            uint256 amount0,
            uint256 amount1,
            address indexed to
        );
        event Swap(
            address indexed sender,
            uint256 amount0In,
            uint256 amount1In,
            uint256 amount0Out,
            uint256 amount1Out,
            address indexed to
        );
        event Sync(uint112 reserve0, uint112 reserve1);
        function MINIMUM_LIQUIDITY() external pure returns (uint256);
        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 (uint256);
        function price1CumulativeLast() external view returns (uint256);
        function kLast() external view returns (uint256);
        function mint(address to) external returns (uint256 liquidity);
        function burn(address to)
            external
            returns (uint256 amount0, uint256 amount1);
        function swap(
            uint256 amount0Out,
            uint256 amount1Out,
            address to,
            bytes calldata data
        ) external;
        function skim(address to) external;
        function sync() external;
        function initialize(address, address) external;
    }
    interface IUniswapV2Factory {
        event PairCreated(
            address indexed token0,
            address indexed token1,
            address pair,
            uint256
        );
        
        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(uint256) external view returns (address pair);
        function allPairsLength() external view returns (uint256);
        function createPair(address tokenA, address tokenB)
            external
            returns (address pair);
        function setFeeTo(address) external;
        function setFeeToSetter(address) external;
    }
    library IterableMapping {
        // Iterable mapping from address to uint;
        struct Map {
            address[] keys;
            mapping(address => uint256) values;
            mapping(address => uint256) indexOf;
            mapping(address => bool) inserted;
        }
        function get(Map storage map, address key) internal view returns (uint256) {
            return map.values[key];
        }
        function getIndexOfKey(Map storage map, address key)
            internal
            view
            returns (int256)
        {
            if (!map.inserted[key]) {
                return -1;
            }
            return int256(map.indexOf[key]);
        }
        function getKeyAtIndex(Map storage map, uint256 index)
            internal
            view
            returns (address)
        {
            return map.keys[index];
        }
        function size(Map storage map) internal view returns (uint256) {
            return map.keys.length;
        }
        function set(
            Map storage map,
            address key,
            uint256 val
        ) internal {
            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) internal {
            if (!map.inserted[key]) {
                return;
            }
            delete map.inserted[key];
            delete map.values[key];
            uint256 index = map.indexOf[key];
            uint256 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();
        }
    }
    interface IERC20 {
        function totalSupply() external view returns (uint256);
        function balanceOf(address account) external view returns (uint256);
        function transfer(address recipient, uint256 amount)
            external
            returns (bool);
        function allowance(address owner, address spender)
            external
            view
            returns (uint256);
        function approve(address spender, uint256 amount) external returns (bool);
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) external returns (bool);
        event Transfer(address indexed from, address indexed to, uint256 value);
        event Approval(
            address indexed owner,
            address indexed spender,
            uint256 value
        );
    }
    interface IERC20Metadata is IERC20 {
        function name() external view returns (string memory);
        function symbol() external view returns (string memory);
        function decimals() external view returns (uint8);
    }
    contract ERC20 is Context, IERC20, IERC20Metadata {
        using SafeMath for uint256;
        mapping(address => uint256) private _balances;
        mapping(address => mapping(address => 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 override returns (string memory) {
            return _name;
        }
        function symbol() public view virtual override returns (string memory) {
            return _symbol;
        }
        function decimals() public view virtual override returns (uint8) {
            return 18;
        }
        function totalSupply() public view virtual override returns (uint256) {
            return _totalSupply;
        }
        function balanceOf(address account)
            public
            view
            virtual
            override
            returns (uint256)
        {
            return _balances[account];
        }
        function transfer(address recipient, uint256 amount)
            public
            virtual
            override
            returns (bool)
        {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
        function allowance(address owner, address spender)
            public
            view
            virtual
            override
            returns (uint256)
        {
            return _allowances[owner][spender];
        }
        function approve(address spender, uint256 amount)
            public
            virtual
            override
            returns (bool)
        {
            _approve(_msgSender(), spender, amount);
            return true;
        }
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) public virtual override returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(
                sender,
                _msgSender(),
                _allowances[sender][_msgSender()].sub(
                    amount,
                    "ERC20: transfer amount exceeds allowance"
                )
            );
            return true;
        }
        function increaseAllowance(address spender, uint256 addedValue)
            public
            virtual
            returns (bool)
        {
            _approve(
                _msgSender(),
                spender,
                _allowances[_msgSender()][spender].add(addedValue)
            );
            return true;
        }
        function decreaseAllowance(address spender, uint256 subtractedValue)
            public
            virtual
            returns (bool)
        {
            _approve(
                _msgSender(),
                spender,
                _allowances[_msgSender()][spender].sub(
                    subtractedValue,
                    "ERC20: decreased allowance below zero"
                )
            );
            return true;
        }
        function _transfer(
            address sender,
            address recipient,
            uint256 amount
        ) internal virtual {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
            _beforeTokenTransfer(sender, recipient, amount);
            _balances[sender] = _balances[sender].sub(
                amount,
                "ERC20: transfer amount exceeds balance"
            );
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
        function _mint(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: mint to the zero address");
            _beforeTokenTransfer(address(0), account, amount);
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
        function _burn(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: burn from the zero address");
            _beforeTokenTransfer(account, address(0), amount);
            _balances[account] = _balances[account].sub(
                amount,
                "ERC20: burn amount exceeds balance"
            );
            _totalSupply = _totalSupply.sub(amount);
            emit Transfer(account, address(0), amount);
        }
        function _approve(
            address owner,
            address spender,
            uint256 amount
        ) internal virtual {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
        function _beforeTokenTransfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {}
    }
    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);
    }
    interface DividendPayingTokenInterface {
        function dividendOf(address _owner) external view returns (uint256);
        function distributeDividends() external payable;
        function withdrawDividend() external;
        event DividendsDistributed(address indexed from, uint256 weiAmount);
        event DividendWithdrawn(address indexed to, uint256 weiAmount);
    }
    library SafeMath {
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
            return c;
        }
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            return sub(a, b, "SafeMath: subtraction overflow");
        }
        function sub(
            uint256 a,
            uint256 b,
            string memory errorMessage
        ) internal pure returns (uint256) {
            require(b <= a, errorMessage);
            uint256 c = a - b;
            return c;
        }
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            if (a == 0) {
                return 0;
            }
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
            return c;
        }
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            return div(a, b, "SafeMath: division by zero");
        }
        function div(
            uint256 a,
            uint256 b,
            string memory errorMessage
        ) internal pure returns (uint256) {
            require(b > 0, errorMessage);
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return c;
        }
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return mod(a, b, "SafeMath: modulo by zero");
        }
        function mod(
            uint256 a,
            uint256 b,
            string memory errorMessage
        ) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    contract Ownable is Context {
        address private _owner;
        event OwnershipTransferred(
            address indexed previousOwner,
            address indexed newOwner
        );
        constructor() {
            address msgSender = _msgSender();
            _owner = msgSender;
            emit OwnershipTransferred(address(0), msgSender);
        }
        function owner() public view returns (address) {
            return _owner;
        }
        modifier onlyOwner() {
            require(_owner == _msgSender(), "Ownable: caller is not the owner");
            _;
        }
        function transferOwnership(address newOwner) public virtual onlyOwner {
            require(
                newOwner != address(0),
                "Ownable: new owner is the zero address"
            );
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    library SafeMathInt {
        int256 private constant MIN_INT256 = int256(1) << 255;
        int256 private constant MAX_INT256 = ~(int256(1) << 255);
        function mul(int256 a, int256 b) internal pure returns (int256) {
            int256 c = a * b;
            require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
            require((b == 0) || (c / b == a));
            return c;
        }
        function div(int256 a, int256 b) internal pure returns (int256) {
            // Prevent overflow when dividing MIN_INT256 by -1
            require(b != -1 || a != MIN_INT256);
            return a / b;
        }
        function sub(int256 a, int256 b) internal pure returns (int256) {
            int256 c = a - b;
            require((b >= 0 && c <= a) || (b < 0 && c > a));
            return c;
        }
        function add(int256 a, int256 b) internal pure returns (int256) {
            int256 c = a + b;
            require((b >= 0 && c >= a) || (b < 0 && c < a));
            return c;
        }
        function abs(int256 a) internal pure returns (int256) {
            require(a != MIN_INT256);
            return a < 0 ? -a : a;
        }
        function toUint256Safe(int256 a) internal pure returns (uint256) {
            require(a >= 0);
            return uint256(a);
        }
    }
    library SafeMathUint {
        function toInt256Safe(uint256 a) internal pure returns (int256) {
            int256 b = int256(a);
            require(b >= 0);
            return b;
        }
    }
    interface IUniswapV2Router01 {
        function factory() external pure returns (address);
        function WETH() external pure returns (address);
        function addLiquidity(
            address tokenA,
            address tokenB,
            uint256 amountADesired,
            uint256 amountBDesired,
            uint256 amountAMin,
            uint256 amountBMin,
            address to,
            uint256 deadline
        )
            external
            returns (
                uint256 amountA,
                uint256 amountB,
                uint256 liquidity
            );
        function addLiquidityETH(
            address token,
            uint256 amountTokenDesired,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline
        )
            external
            payable
            returns (
                uint256 amountToken,
                uint256 amountETH,
                uint256 liquidity
            );
        function removeLiquidity(
            address tokenA,
            address tokenB,
            uint256 liquidity,
            uint256 amountAMin,
            uint256 amountBMin,
            address to,
            uint256 deadline
        ) external returns (uint256 amountA, uint256 amountB);
        function removeLiquidityETH(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline
        ) external returns (uint256 amountToken, uint256 amountETH);
        function removeLiquidityWithPermit(
            address tokenA,
            address tokenB,
            uint256 liquidity,
            uint256 amountAMin,
            uint256 amountBMin,
            address to,
            uint256 deadline,
            bool approveMax,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external returns (uint256 amountA, uint256 amountB);
        function removeLiquidityETHWithPermit(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline,
            bool approveMax,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external returns (uint256 amountToken, uint256 amountETH);
        function swapExactTokensForTokens(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
        function swapTokensForExactTokens(
            uint256 amountOut,
            uint256 amountInMax,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
        function swapExactETHForTokens(
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external payable returns (uint256[] memory amounts);
        function swapTokensForExactETH(
            uint256 amountOut,
            uint256 amountInMax,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
        function swapExactTokensForETH(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
        function swapETHForExactTokens(
            uint256 amountOut,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external payable returns (uint256[] memory amounts);
        function quote(
            uint256 amountA,
            uint256 reserveA,
            uint256 reserveB
        ) external pure returns (uint256 amountB);
        function getAmountOut(
            uint256 amountIn,
            uint256 reserveIn,
            uint256 reserveOut
        ) external pure returns (uint256 amountOut);
        function getAmountIn(
            uint256 amountOut,
            uint256 reserveIn,
            uint256 reserveOut
        ) external pure returns (uint256 amountIn);
        function getAmountsOut(uint256 amountIn, address[] calldata path)
            external
            view
            returns (uint256[] memory amounts);
        function getAmountsIn(uint256 amountOut, address[] calldata path)
            external
            view
            returns (uint256[] memory amounts);
    }
    interface IUniswapV2Router02 is IUniswapV2Router01 {
        function removeLiquidityETHSupportingFeeOnTransferTokens(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline
        ) external returns (uint256 amountETH);
        function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline,
            bool approveMax,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external returns (uint256 amountETH);
        function swapExactTokensForTokensSupportingFeeOnTransferTokens(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external;
        function swapExactETHForTokensSupportingFeeOnTransferTokens(
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external payable;
        function swapExactTokensForETHSupportingFeeOnTransferTokens(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external;
    }
    contract DividendPayingToken is
        ERC20,
        DividendPayingTokenInterface,
        DividendPayingTokenOptionalInterface
    {
        using SafeMath for uint256;
        using SafeMathUint for uint256;
        using SafeMathInt for int256;
        uint256 internal constant magnitude = 2**128;
        uint256 internal magnifiedDividendPerShare;
        mapping(address => int256) internal magnifiedDividendCorrections;
        mapping(address => uint256) internal withdrawnDividends;
        uint256 public totalDividendsDistributed;
        constructor(string memory _name, string memory _symbol)
            ERC20(_name, _symbol)
        {}
        receive() external payable {
            distributeDividends();
        }
        function distributeDividends() public payable override {
            require(totalSupply() > 0);
            if (msg.value > 0) {
                magnifiedDividendPerShare = magnifiedDividendPerShare.add(
                    (msg.value).mul(magnitude) / totalSupply()
                );
                emit DividendsDistributed(msg.sender, msg.value);
                totalDividendsDistributed = totalDividendsDistributed.add(
                    msg.value
                );
            }
        }
        function withdrawDividend() public virtual override {
            _withdrawDividendOfUser(payable(msg.sender));
        }
        function _withdrawDividendOfUser(address payable user)
            internal
            virtual
            returns (uint256)
        {
            uint256 _withdrawableDividend = withdrawableDividendOf(user);
            if (_withdrawableDividend > 0) {
                withdrawnDividends[user] = withdrawnDividends[user].add(
                    _withdrawableDividend
                );
                emit DividendWithdrawn(user, _withdrawableDividend);
                (bool success, ) = user.call{
                    value: _withdrawableDividend,
                    gas: 3000
                }("");
                if (!success) {
                    withdrawnDividends[user] = withdrawnDividends[user].sub(
                        _withdrawableDividend
                    );
                    return 0;
                }
                return _withdrawableDividend;
            }
            return 0;
        }
        function dividendOf(address _owner) public view override returns (uint256) {
            return withdrawableDividendOf(_owner);
        }
        function withdrawableDividendOf(address _owner)
            public
            view
            override
            returns (uint256)
        {
            return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
        }
        function withdrawnDividendOf(address _owner)
            public
            view
            override
            returns (uint256)
        {
            return withdrawnDividends[_owner];
        }
        function accumulativeDividendOf(address _owner)
            public
            view
            override
            returns (uint256)
        {
            return
                magnifiedDividendPerShare
                    .mul(balanceOf(_owner))
                    .toInt256Safe()
                    .add(magnifiedDividendCorrections[_owner])
                    .toUint256Safe() / magnitude;
        }
        function _transfer(
            address from,
            address to,
            uint256 value
        ) internal virtual override {
            require(false);
            int256 _magCorrection = magnifiedDividendPerShare
                .mul(value)
                .toInt256Safe();
            magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from]
                .add(_magCorrection);
            magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(
                _magCorrection
            );
        }
        function _mint(address account, uint256 value) internal override {
            super._mint(account, value);
            magnifiedDividendCorrections[account] = magnifiedDividendCorrections[
                account
            ].sub((magnifiedDividendPerShare.mul(value)).toInt256Safe());
        }
        function _burn(address account, uint256 value) internal override {
            super._burn(account, value);
            magnifiedDividendCorrections[account] = magnifiedDividendCorrections[
                account
            ].add((magnifiedDividendPerShare.mul(value)).toInt256Safe());
        }
        function _setBalance(address account, uint256 newBalance) internal {
            uint256 currentBalance = balanceOf(account);
            if (newBalance > currentBalance) {
                uint256 mintAmount = newBalance.sub(currentBalance);
                _mint(account, mintAmount);
            } else if (newBalance < currentBalance) {
                uint256 burnAmount = currentBalance.sub(newBalance);
                _burn(account, burnAmount);
            }
        }
    }
    contract RuffRuff is ERC20, Ownable {
        using SafeMath for uint256;
        IUniswapV2Router02 public uniswapV2Router;
        address public uniswapV2Pair;
        bool private swapping;
        bool private stakingEnabled = false;
        bool public tradingEnabled = false;
        RuffRuffDividendTracker public dividendTracker;
        address public liquidityWallet;
        address payable public marketingAddress =
            payable(0xc00991c80F10df939E57B6fFa298fCa5737Ae706);
        address payable public marketingAddress2 =
            payable(0x027aBf2e14bc9Aa5126CF0dE7Aa687B474776383);
        uint256 public maxWalletSize = 20000000 * 10**9; // 2% Max
        uint256 public swapTokensAtAmount = 200000 * (10**9);
        uint256 public swapTokensAtAmountMax = 5000000 * (10**9);
        uint256 public devFees = 3;
        uint256 public devFeesReferred = 2;
        uint256 public liquidityFee = 1;
        uint256 public liquidityFeeReferred = 0;
        uint256 public BNBRewardsBuyFee = 0;
        uint256 public BNBRewardsBuyFeeReferred = 0;
        uint256 public BNBRewardsSellFee = 0;
        uint256 public BNBRewardsSellFeeReferred = 0;
        uint256 private countDevFees = 0;
        uint256 private countLiquidityFees = 0;
        uint256 private countBNBRewardsFee = 0;
        mapping(address => mapping(int256 => address)) public referrerTree;
        mapping(address => bool) private convertReferrals;
        mapping(address => uint256) private unconvertedTokens;
        uint256 public unconvertedTokensIndex;
        uint256 public unconvertedTokensIndexUpper;
        mapping(uint256 => address) private unconvertedTokensKeys;
        bool public enableConvertingReferralRewards;
        uint256 public referralFee; // referral fees are split up by the referralTreeFees
        mapping(int256 => uint256) public referralTreeFees;
        int256 private referralTreeFeesLength;
        mapping(address => uint256) public referralCount;
        mapping(address => uint256) public referralCountBranched;
        mapping(address => uint256) public referralEarnings;
        mapping(address => uint256) public referralEarningsConverted;
        mapping(address => uint256) public referralEarningsConvertedInPayout;
        uint256 public totalReferralsDistributed;
        uint256 public totalReferralsDistributedConverted;
        uint256 public totalReferralsDistributedConvertedInPayout;
        uint256 private iteration = 0;
        uint256 private iterationDaily = 0;
        uint256 private iterationWeekly = 0;
        uint256 private iterationMonthly = 0;
        uint256 public dailyTimer = block.timestamp + 86400;
        uint256 public weeklyTimer = block.timestamp + 604800;
        uint256 public monthlyTimer = block.timestamp + 2629743;
        bool public swapAndLiquifyEnabled = true;
        uint256 public gasForProcessing = 300000;
        mapping(address => bool) private _isExcludedFromFees;
        mapping(address => bool) public automatedMarketMakerPairs;
        mapping(address => uint256) public stakingBonus;
        mapping(address => uint256) public stakingUntilDate;
        mapping(uint256 => uint256) public stakingAmounts;
        mapping(address => bool) private canTransferBeforeTradingIsEnabled;
        event EnableSwapAndLiquify(bool enabled);
        event UpdateDividendTracker(
            address indexed newAddress,
            address indexed oldAddress
        );
        event UpdateUniswapV2Router(
            address indexed newAddress,
            address indexed oldAddress
        );
        event UpdateFees(
            uint256 dev,
            uint256 liquidity,
            uint256 BNBRewardsBuy,
            uint256 BNBRewardsSell,
            uint256 referralFee
        );
        event UpdateFeesReferred(
            uint256 dev,
            uint256 liquidity,
            uint256 BNBRewardsBuy,
            uint256 BNBRewardsSell
        );
        event UpdateReferralTreeFees(int256 index, uint256 fee);
        event ExcludeFromFees(address indexed account, bool isExcluded);
        event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
        event LiquidityWalletUpdated(
            address indexed newLiquidityWallet,
            address indexed oldLiquidityWallet
        );
        event GasForProcessingUpdated(
            uint256 indexed newValue,
            uint256 indexed oldValue
        );
        event SwapAndLiquify(
            uint256 tokensSwapped,
            uint256 ethReceived,
            uint256 tokensIntoLiqudity,
            bool success
        );
        event SendDividends(uint256 dividends, uint256 marketing, bool success);
        event ProcessedDividendTracker(
            uint256 iterations,
            uint256 claims,
            uint256 lastProcessedIndex,
            bool indexed automatic,
            uint256 gas,
            address indexed processor
        );
        event UpdatePayoutToken(address account, address token);
        event UpdateAllowTokens(address token, bool allow);
        event ReferralRewards(
            address from,
            address indexed to,
            uint256 indexed amount,
            uint256 iterationDaily,
            uint256 iterationWeekly,
            uint256 iterationMonthly,
            int256 treePosition,
            int256 indexed bnbAmount
        );
        event ReferredBy(
            address indexed by,
            address indexed referree,
            uint256 iterationDaily,
            uint256 iterationWeekly,
            uint256 iterationMonthly
        );
        event LeaderboardCompletion(uint8 leaderboardCase, uint256 iteration);
        constructor() ERC20("RuffRuff", "RUFF") {
            dividendTracker = new RuffRuffDividendTracker(payable(this));
            liquidityWallet = owner();
            uniswapV2Router = IUniswapV2Router02(
                // 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D //mainnet
                0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D //testnet
                
            );
            // Create a uniswap pair for this new token
            uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair(
                    address(this),
                    uniswapV2Router.WETH()
                );
            _setAutomatedMarketMakerPair(uniswapV2Pair, true);
            // exclude from receiving dividends
            dividendTracker.excludeFromDividends(address(dividendTracker));
            dividendTracker.excludeFromDividends(address(this));
            dividendTracker.excludeFromDividends(
                0x000000000000000000000000000000000000dEaD
            );
            dividendTracker.excludedFromDividends(address(0));
            dividendTracker.excludeFromDividends(owner());
            dividendTracker.excludeFromDividends(address(uniswapV2Router));
            // exclude from paying fees or having max transaction amount
            _isExcludedFromFees[liquidityWallet] = true;
            _isExcludedFromFees[address(this)] = true;
            _isExcludedFromFees[owner()] = true;
            _isExcludedFromFees[address(dividendTracker)] = true;
            referralTreeFees[0] = 100; // 1% to primary referrer
            referralTreeFees[1] = 60; // 0.6% to secondary referrer
            referralTreeFees[2] = 40; // 0.4% to tertiary referrer
            referralTreeFeesLength = 3;
            calculateReferralFee();
            canTransferBeforeTradingIsEnabled[owner()] = true;
            /*
                _mint is an internal function in ERC20.sol that is only called here,
                and CANNOT be called ever again
            */
            _mint(owner(), 1000000000 * (10**9));
        }
        function decimals() public view virtual override returns (uint8) {
            return 9;
        }
        receive() external payable {}
        function updateStakingAmounts(uint256 duration, uint256 bonus)
            public
            onlyOwner
        {
            require(stakingAmounts[duration] != bonus);
            require(bonus <= 100, "Staking bonus can't exceed 100");
            require(bonus > 0, "Staking bonus can't be 0");
            stakingAmounts[duration] = bonus;
        }
        function setMaxWalletSize(uint256 newMaxWalletSize) public onlyOwner {
        maxWalletSize = newMaxWalletSize;
        }
        function enableTrading() external onlyOwner {
            require(!tradingEnabled, "trading already enabled");
            tradingEnabled = true;
            enableConvertingReferralRewards = true;
            blockNumEnabled = block.number;
        }
        function setPresaleWallet(address wallet) external onlyOwner {
            canTransferBeforeTradingIsEnabled[wallet] = true;
            _isExcludedFromFees[wallet] = true;
            dividendTracker.excludeFromDividends(wallet);
        }
        function updateDividendTracker(address newAddress) public onlyOwner {
            require(newAddress != address(dividendTracker));
            RuffRuffDividendTracker newDividendTracker = RuffRuffDividendTracker(
                payable(newAddress)
            );
            require(newDividendTracker.owner() == address(this));
            newDividendTracker.excludeFromDividends(address(newDividendTracker));
            newDividendTracker.excludeFromDividends(address(this));
            newDividendTracker.excludeFromDividends(owner());
            newDividendTracker.excludeFromDividends(address(uniswapV2Router));
            emit UpdateDividendTracker(newAddress, address(dividendTracker));
            dividendTracker = newDividendTracker;
        }
       
        function setMarketingAddress(address payable newAddress) public onlyOwner {
            marketingAddress = newAddress;
        }
        function setMarketingAddress2(address payable newAddress2)
            public
            onlyOwner
        {
            marketingAddress2 = newAddress2;
        }
        function updateUniswapV2Router(address newAddress) public onlyOwner {
            require(newAddress != address(uniswapV2Router));
            emit UpdateUniswapV2Router(newAddress, address(uniswapV2Router));
            uniswapV2Router = IUniswapV2Router02(newAddress);
            dividendTracker.updateUniswapV2Router(newAddress);
        }
        function excludeFromFees(address account, bool excluded) public onlyOwner {
            require(_isExcludedFromFees[account] != excluded);
            _isExcludedFromFees[account] = excluded;
            emit ExcludeFromFees(account, excluded);
        }
        function enableSwapAndLiquify(bool enabled) public onlyOwner {
            require(swapAndLiquifyEnabled != enabled);
            swapAndLiquifyEnabled = enabled;
            emit EnableSwapAndLiquify(enabled);
        }
        function setAutomatedMarketMakerPair(address pair, bool value)
            public
            onlyOwner
        {
            require(pair != uniswapV2Pair);
            _setAutomatedMarketMakerPair(pair, value);
        }
        function setAllowCustomTokens(bool allow) public onlyOwner {
            dividendTracker.setAllowCustomTokens(allow);
        }
        function setAllowAutoReinvest(bool allow) public onlyOwner {
            dividendTracker.setAllowAutoReinvest(allow);
        }
        function _setAutomatedMarketMakerPair(address pair, bool value) private {
            automatedMarketMakerPairs[pair] = value;
            if (value) {
                dividendTracker.excludeFromDividends(pair);
            }
            emit SetAutomatedMarketMakerPair(pair, value);
        }
        function updateLiquidityWallet(address newLiquidityWallet)
            public
            onlyOwner
        {
            excludeFromFees(newLiquidityWallet, true);
            emit LiquidityWalletUpdated(newLiquidityWallet, liquidityWallet);
            liquidityWallet = newLiquidityWallet;
        }
        function updateGasForProcessing(uint256 newValue) public onlyOwner {
            require(
                newValue >= 200000 && newValue <= 500000,
                "new gas value must be between 200000 and 500000"
            );
            gasForProcessing = newValue;
        }
        function updateFees(
            uint256 dev,
            uint256 liquidity,
            uint256 BNBRewardsBuy,
            uint256 BNBRewardsSell,
            uint256 referral
        ) public onlyOwner {
            devFees = dev;
            liquidityFee = liquidity;
            BNBRewardsBuyFee = BNBRewardsBuy;
            BNBRewardsSellFee = BNBRewardsSell;
            referralFee = referral;
            emit UpdateFees(
                dev,
                liquidity,
                BNBRewardsBuy,
                BNBRewardsSell,
                referralFee
            );
        }
        function updateFeesReferred(
            uint256 devReferred,
            uint256 liquidityReferred,
            uint256 BNBRewardsBuyReferred,
            uint256 BNBRewardsSellReferred
        ) public onlyOwner {
            require(BNBRewardsBuyReferred <= 2, "Cannot set BNBreward fee over 2%");
            require(
                BNBRewardsSellReferred <= 2,
                "Cannot set BNBreward fee over 2%"
            );
            require(devReferred <= 10, "Cannot set dev fee over 10%");
            require(liquidityReferred <= 10, "Cannot set liquidity fee over 10%");
            devFeesReferred = devReferred;
            liquidityFeeReferred = liquidityReferred;
            BNBRewardsBuyFeeReferred = BNBRewardsBuyReferred;
            BNBRewardsSellFeeReferred = BNBRewardsSellReferred;
            emit UpdateFeesReferred(
                devReferred,
                liquidityReferred,
                BNBRewardsBuyReferred,
                BNBRewardsSellReferred
            );
        }
        // returns with two decimals of precision. i.e. "123" == "1.23%"
        function getReferralTreeFees(int256 index) public view returns (uint256) {
            return referralTreeFees[index];
        }
        function getReferralTreeFeesLength() public view returns (int256) {
            return referralTreeFeesLength;
        }
        function calculateReferralFee() private {
            uint256 referralTreeFeesAdded;
            for (int256 i = 0; i < referralTreeFeesLength; i++) {
                referralTreeFeesAdded += referralTreeFees[i];
            }
            referralFee = referralTreeFeesAdded / 100;
        }
        function setReferralTreeFeesLength(int256 length) public onlyOwner {
            referralTreeFeesLength = length;
            calculateReferralFee();
        }
        function updateReferralTreeFees(int256 index, uint256 fee)
            public
            onlyOwner
        {
            referralTreeFees[index] = fee;
            calculateReferralFee();
            emit UpdateReferralTreeFees(index, fee);
        }
        function getTotalDividendsDistributed() external view returns (uint256) {
            return dividendTracker.totalDividendsDistributed();
        }
        function isExcludedFromFees(address account) public view returns (bool) {
            return _isExcludedFromFees[account];
        }
        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 getAccountDividendsInfo(address account)
            external
            view
            returns (
                address,
                int256,
                int256,
                uint256,
                uint256,
                uint256
            )
        {
            return dividendTracker.getAccount(account);
        }
        function getAccountDividendsInfoAtIndex(uint256 index)
            external
            view
            returns (
                address,
                int256,
                int256,
                uint256,
                uint256,
                uint256
            )
        {
            return dividendTracker.getAccountAtIndex(index);
        }
        function processDividendTracker(uint256 gas) external {
            (
                uint256 iterations,
                uint256 claims,
                uint256 lastProcessedIndex
            ) = dividendTracker.process(gas);
            emit ProcessedDividendTracker(
                iterations,
                claims,
                lastProcessedIndex,
                false,
                gas,
                tx.origin
            );
        }
        function claim() external {
            dividendTracker.processAccount(payable(msg.sender), false);
        }
        function getLastProcessedIndex() external view returns (uint256) {
            return dividendTracker.getLastProcessedIndex();
        }
        function getNumberOfDividendTokenHolders() external view returns (uint256) {
            return dividendTracker.getNumberOfTokenHolders();
        }
        function setAutoClaim(bool value) external {
            dividendTracker.setAutoClaim(msg.sender, value);
        }
        function setReinvest(bool value) external {
            dividendTracker.setReinvest(msg.sender, value);
        }
        function setDividendsPaused(bool value) external onlyOwner {
            dividendTracker.setDividendsPaused(value);
        }
        function isExcludedFromAutoClaim(address account)
            external
            view
            returns (bool)
        {
            return dividendTracker.isExcludedFromAutoClaim(account);
        }
        function isReinvest(address account) external view returns (bool) {
            return dividendTracker.isReinvest(account);
        }
        function getETHBalance() external view returns (uint256) {
            return address(this).balance;
        }
        function transferETH(address destination, uint256 bnb) external onlyOwner {
            payable(destination).transfer(bnb);
        }
        function getNativeBalance() external view returns (uint256) {
            return balanceOf(address(this));
        }
        function getCountOfFeesToSwap()
            external
            view
            returns (
                uint256,
                uint256,
                uint256
            )
        {
            return (countBNBRewardsFee, countDevFees, countLiquidityFees);
        }
        function transferERC20Token(
            address tokenAddress,
            uint256 amount,
            address destination
        ) external onlyOwner {
            require(tokenAddress != address(this), "Cannot remove native token");
            ERC20(tokenAddress).transfer(destination, amount);
        }
        uint256 private originalAmountBeforeFees;
        uint256 private devFeeActual;
        uint256 private liquidityFeeActual;
        uint256 private BNBRewardsBuyFeeActual;
        uint256 private BNBRewardsSellFeeActual;
        uint256 private totalBuyFeesActual;
        uint256 private totalSellFeesActual;
        uint256 private blockNumEnabled;
        uint256 private earlyBlocks;
        uint256 private earlyTax;
        function _transfer(
            address from,
            address to,
            uint256 amount
        ) internal override {
            require(from != address(0), "ERC20: transfer from the zero address");
            require(
                tradingEnabled || canTransferBeforeTradingIsEnabled[from],
                "Trading has not yet been enabled"
            );
            if (from != uniswapV2Pair) {
                require(
                    to != address(this),
                    "You cannot send tokens to the contract address!"
                );
            }
            if (amount == 0) {
                super._transfer(from, to, 0);
                return;
            } else if (
                !swapping &&
                !_isExcludedFromFees[from] &&
                !_isExcludedFromFees[to] &&
                (to == address(uniswapV2Pair) || from == address(uniswapV2Pair))
            ) {
                bool isSelling = automatedMarketMakerPairs[to];
                devFeeActual = devFees;
                liquidityFeeActual = liquidityFee;
                BNBRewardsBuyFeeActual = BNBRewardsBuyFee;
                BNBRewardsSellFeeActual = BNBRewardsSellFee;
                bool isReferredOnBuy = false;
                address referrer = address(
                    0x0000000000000000000000000000000000000000
                );
                // if the user has been referred by someone and is buying, change to special fees
                if ((getReferrerOf(to) != referrer) && !isSelling) {
                    isReferredOnBuy = true;
                    referrer = getReferrerOf(to);
                    devFees = devFeesReferred;
                    liquidityFee = liquidityFeeReferred;
                    BNBRewardsBuyFee = BNBRewardsBuyFeeReferred;
                    BNBRewardsSellFee = BNBRewardsSellFeeReferred;
                }
                if (block.number < blockNumEnabled + earlyBlocks) {
                    devFees = earlyTax;
                    liquidityFee = 0;
                    BNBRewardsBuyFee = 0;
                    BNBRewardsSellFee = 0;
                }
                if(to != uniswapV2Pair) {
                    require(ERC20.balanceOf(to) + amount < maxWalletSize, "TOKEN: Balance exceeds wallet size!");
                }
                uint256 contractTokenBalance = balanceOf(address(this));
                // convert referral rewards into payout token
                if (
                    unconvertedTokensIndexUpper > 0 &&
                    enableConvertingReferralRewards &&
                    isSelling
                ) {
                    uint256 toConvert = getUnconvertedReferralRewards(
                        unconvertedTokensKeys[unconvertedTokensIndex]
                    );
                    if (toConvert <= 0) {
                        unconvertedTokensIndex++;
                    } else {
                        if (toConvert > swapTokensAtAmountMax) {
                            toConvert = swapTokensAtAmountMax;
                        }
                        swapTokensForPayoutToken(
                            from,
                            toConvert,
                            payable(unconvertedTokensKeys[unconvertedTokensIndex])
                        );
                    }
                }
                bool canSwap = contractTokenBalance >= swapTokensAtAmount;
                if (canSwap && !automatedMarketMakerPairs[from]) {
                    swapping = true;
                    if (swapAndLiquifyEnabled) {
                        swapAndLiquify(countLiquidityFees);
                    }
                    swapAndSendDividendsAndMarketingFunds(
                        countBNBRewardsFee,
                        countDevFees
                    );
                    swapping = false;
                }
                originalAmountBeforeFees = amount;
                /*
                    Referral System
                */
                uint256 referralFeeTxn = amount.mul(referralFee).div(100);
                if (isReferredOnBuy) {
                    for (int256 i = 0; i < referralTreeFeesLength; i++) {
                        address treePayoutTo = referrerTree[to][i];
                        uint256 adjustedTax = originalAmountBeforeFees
                            .mul(referralTreeFees[i])
                            .div(10000);
                        if (
                            treePayoutTo ==
                            address(0x0000000000000000000000000000000000000000)
                        ) {
                            break;
                        }
                        amount = amount.sub(adjustedTax);
                        if (
                            !getConvertReferralRewards(treePayoutTo) ||
                            !enableConvertingReferralRewards
                        ) {
                            super._transfer(from, treePayoutTo, adjustedTax);
                            dividendTracker.setBalance(
                                treePayoutTo,
                                getStakingBalance(treePayoutTo)
                            );
                            referralEarnings[treePayoutTo] += adjustedTax;
                            totalReferralsDistributed += adjustedTax;
                            referralFeeTxn -= adjustedTax;
                            emit ReferralRewards(
                                from,
                                treePayoutTo,
                                adjustedTax,
                                iterationDaily,
                                iterationWeekly,
                                iterationMonthly,
                                i,
                                -1
                            );
                        } else {
                            super._transfer(from, address(this), adjustedTax);
                            if (getUnconvertedReferralRewards(treePayoutTo) <= 0) {
                                unconvertedTokensKeys[
                                    unconvertedTokensIndexUpper
                                ] = treePayoutTo;
                                unconvertedTokensIndexUpper++;
                            }
                            unconvertedTokens[treePayoutTo] += adjustedTax;
                            referralFeeTxn -= adjustedTax;
                        }
                    }
                    if (referralFeeTxn > 0) {
                        amount = amount.sub(referralFeeTxn);
                        super._transfer(from, address(this), referralFeeTxn);
                        countBNBRewardsFee += referralFeeTxn;
                    }
                } else if (!isSelling) {
                    // if not referred on buy, use the referral tax towards passive earn rewards
                    amount = amount.sub(referralFeeTxn);
                    super._transfer(from, address(this), referralFeeTxn);
                    countBNBRewardsFee += referralFeeTxn;
                }
                /*
                
                */
                uint256 BNBRewardsFee = isSelling
                    ? BNBRewardsSellFee
                    : BNBRewardsBuyFee;
                uint256 devFeeAmount = originalAmountBeforeFees.mul(devFees).div(
                    100
                );
                uint256 liquidityFeeAmount = originalAmountBeforeFees
                    .mul(liquidityFee)
                    .div(100);
                uint256 BNBRewardsFeeAmount = originalAmountBeforeFees
                    .mul(BNBRewardsFee)
                    .div(100);
                countDevFees += devFeeAmount;
                countLiquidityFees += liquidityFeeAmount;
                countBNBRewardsFee += BNBRewardsFeeAmount;
                uint256 fees = devFeeAmount +
                    liquidityFeeAmount +
                    BNBRewardsFeeAmount;
                amount = amount.sub(fees);
                super._transfer(from, address(this), fees);
                uint256 gas = gasForProcessing;
                try dividendTracker.process(gas) returns (
                    uint256 iterations,
                    uint256 claims,
                    uint256 lastProcessedIndex
                ) {
                    emit ProcessedDividendTracker(
                        iterations,
                        claims,
                        lastProcessedIndex,
                        true,
                        gas,
                        tx.origin
                    );
                } catch {}
                // set fees back to normal values
                if (isReferredOnBuy) {
                    devFees = devFeeActual;
                    liquidityFee = liquidityFeeActual;
                    BNBRewardsBuyFee = BNBRewardsBuyFeeActual;
                    BNBRewardsSellFee = BNBRewardsSellFeeActual;
                }
            }
            super._transfer(from, to, amount);
            dividendTracker.setBalance(from, getStakingBalance(from));
            dividendTracker.setBalance(to, getStakingBalance(to));
            updateReferralLeaderboards();
        }
        function getStakingBalance(address account) private view returns (uint256) {
            return
                stakingEnabled
                    ? balanceOf(account).mul(stakingBonus[account].add(100)).div(
                        100
                    )
                    : balanceOf(account);
        }
        function swapAndLiquify(uint256 tokens) private {
            if (tokens > balanceOf(address(this))) {
                emit SwapAndLiquify(0, 0, 0, false);
                return;
            }
            // avoid price impact errors with large transactions
            if (tokens > swapTokensAtAmountMax) {
                tokens = swapTokensAtAmountMax;
            }
            // split the contract balance into halves
            uint256 half = tokens.div(2);
            uint256 otherHalf = tokens.sub(half);
            if (half <= 0 || otherHalf <= 0) {
                return;
            }
            // capture the contract's current ETH balance.
            // this is so that we can capture exactly the amount of ETH that the
            // swap creates, and not make the liquidity event include any ETH that
            // has been manually sent to the contract
            uint256 initialBalance = address(this).balance;
            // swap tokens for ETH
            swapTokensForEth(half, payable(address(this)));
            countLiquidityFees -= half;
            // how much ETH did we just swap into?
            uint256 newBalance = address(this).balance.sub(initialBalance);
            // add liquidity to uniswap
            addLiquidity(otherHalf, newBalance);
            countLiquidityFees -= otherHalf;
            emit SwapAndLiquify(half, newBalance, otherHalf, true);
        }
        function setSwapTokensAmount(uint256 amount) public onlyOwner {
            require(amount <= 20000000, "cannot set swap amount greater than .2%");
            swapTokensAtAmount = amount;
        }
        function setSwapTokensAmountMax(uint256 amount) public onlyOwner {
            require(
                amount > swapTokensAtAmount,
                "Max amount must be greater than minimum"
            );
            require(amount <= 20000000, "cannot set swap amount greater than .2%");
            swapTokensAtAmountMax = amount;
        }
        function swapTokensForEth(uint256 tokenAmount, address payable account)
            private
        {
            if (tokenAmount <= 0) {
                return;
            }
            if (balanceOf(address(this)) < tokenAmount) {
                tokenAmount = balanceOf(address(this));
            }
            // generate the uniswap pair path of token -> weth
            address[] memory path = new address[](2);
            path[0] = address(this);
            path[1] = uniswapV2Router.WETH();
            _approve(address(this), address(uniswapV2Router), tokenAmount);
            // make the swap
            uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                tokenAmount,
                0, // accept any amount of ETH
                path,
                account,
                block.timestamp
            );
        }
        address private upcoming = address(0);
        uint256 private upcomingAmount = 0;
        address private upcomingFrom = address(0);
        function clearUnconvertedEntry() private {
            unconvertedTokens[unconvertedTokensKeys[unconvertedTokensIndex]] = 0;
            unconvertedTokensKeys[unconvertedTokensIndex] = address(0);
            unconvertedTokensIndex++;
            if (unconvertedTokensIndex >= unconvertedTokensIndexUpper) {
                unconvertedTokensIndex = 0;
                unconvertedTokensIndexUpper = 0;
            }
        }
        function swapTokensForPayoutToken(
            address fromOriginal,
            uint256 tokenAmount,
            address payable account
        ) private {
            if (tokenAmount <= 0) {
                return;
            }
            uint256 initialBalance;
            uint256 newBalance;
            if (dividendTracker.getPayoutToken(account) == address(0)) {
                initialBalance = address(this).balance;
                swapTokensForEth(tokenAmount, account);
                newBalance = address(this).balance.sub(initialBalance);
                referralEarningsConverted[account] += tokenAmount;
                totalReferralsDistributedConverted += tokenAmount;
                referralEarningsConvertedInPayout[account] += newBalance;
                totalReferralsDistributedConvertedInPayout += newBalance;
                emit ReferralRewards(
                    fromOriginal,
                    account,
                    unconvertedTokens[account],
                    iterationDaily,
                    iterationWeekly,
                    iterationMonthly,
                    int256(-1),
                    int256(newBalance)
                );
                clearUnconvertedEntry();
                if (upcoming == address(0)) {
                    return;
                }
            } else if (upcoming == address(0)) {
                initialBalance = address(this).balance;
                swapTokensForEth(tokenAmount, payable(address(this)));
                newBalance = address(this).balance.sub(initialBalance);
                referralEarningsConverted[account] += tokenAmount;
                totalReferralsDistributedConverted += tokenAmount;
                upcoming = account;
                upcomingAmount = newBalance;
                upcomingFrom = fromOriginal;
                clearUnconvertedEntry();
                return;
            }
            address[] memory path = new address[](2);
            path[0] = uniswapV2Router.WETH();
            path[1] = dividendTracker.getPayoutToken(upcoming);
            try
                uniswapV2Router.swapExactETHForTokensSupportingFeeOnTransferTokens{
                    value: upcomingAmount
                }(0, path, upcoming, block.timestamp)
            {} catch {}
            referralEarningsConvertedInPayout[upcoming] += upcomingAmount;
            totalReferralsDistributedConvertedInPayout += upcomingAmount;
            emit ReferralRewards(
                upcomingFrom,
                upcoming,
                upcomingAmount,
                iterationDaily,
                iterationWeekly,
                iterationMonthly,
                int256(-1),
                int256(upcomingAmount)
            );
            if (dividendTracker.getPayoutToken(account) != address(0)) {
                upcoming = account;
                upcomingAmount = newBalance;
                upcomingFrom = fromOriginal;
            } else {
                upcoming = address(0);
                upcomingAmount = 0;
                upcomingFrom = address(0);
            }
            clearUnconvertedEntry();
        }
        function getUnconvertedReferralRewardsIndexAt(uint256 index)
            public
            view
            returns (
                address,
                uint256,
                uint256
            )
        {
            return (
                unconvertedTokensKeys[index],
                unconvertedTokensIndexUpper,
                unconvertedTokens[unconvertedTokensKeys[index]]
            );
        }
        function updatePayoutToken(address token) public {
            require(
                balanceOf(msg.sender) > 0,
                "You must own more than zero $RUFF tokens to switch your payout token!"
            );
            require(token != address(this));
            dividendTracker.updatePayoutToken(msg.sender, token);
            emit UpdatePayoutToken(msg.sender, token);
        }
        function getPayoutToken(address account) public view returns (address) {
            return dividendTracker.getPayoutToken(account);
        }
        function updateAllowTokens(address token, bool allow) public onlyOwner {
            require(token != address(this), "Cannot use native token address");
            dividendTracker.updateAllowTokens(token, allow);
            emit UpdateAllowTokens(token, allow);
        }
        function getAllowTokens(address token) public view returns (bool) {
            return dividendTracker.getAllowTokens(token);
        }
        function setReferrer(address _referrer) public {
            require(_referrer != address(0), "Not a valid referrer");
            require(_referrer != msg.sender, "You cannot refer yourself");
            require(
                referrerTree[msg.sender][0] == address(0),
                "Referrer cannot be changed!"
            );
            // add the direct referrer to the user's payout tree
            referrerTree[msg.sender][0] = _referrer;
            referralCount[_referrer] = referralCount[_referrer] + 1;
            // check if the referrer was referred through a tree of their own;
            // set payout tree accordingly if so
            for (int256 i = 0; i < referralTreeFeesLength - 1; i++) {
                address treeAddress = referrerTree[_referrer][i];
                if (
                    treeAddress ==
                    address(0x0000000000000000000000000000000000000000)
                ) {
                    break;
                }
                referrerTree[msg.sender][i + 1] = treeAddress;
                referralCountBranched[treeAddress] =
                    referralCountBranched[treeAddress] +
                    1;
            }
            emit ReferredBy(
                _referrer,
                msg.sender,
                iterationDaily,
                iterationWeekly,
                iterationMonthly
            );
        }
        function getReferrer() public view returns (address) {
            return referrerTree[msg.sender][0];
        }
        function getReferrerOf(address account) public view returns (address) {
            return referrerTree[account][0];
        }
        function getReferralCount(address account) public view returns (uint256) {
            return referralCount[account];
        }
        function getReferralCountBranched(address account)
            public
            view
            returns (uint256)
        {
            return referralCountBranched[account];
        }
        function getReferralEarnings(address account)
            public
            view
            returns (uint256)
        {
            return referralEarnings[account];
        }
        function getReferralTree(address account, int256 index)
            public
            view
            returns (address)
        {
            return referrerTree[account][index];
        }
        function setReferralTreeAtIndex(
            address account,
            int256 index,
            address accountToInsert
        ) public onlyOwner {
            referrerTree[account][index] = accountToInsert;
        }
        function getReferralTreeLength(address account)
            public
            view
            returns (int256)
        {
            for (int256 i = 0; i < referralTreeFeesLength; i++) {
                if (
                    referrerTree[account][i] ==
                    address(0x0000000000000000000000000000000000000000)
                ) {
                    return i;
                }
            }
            return -1;
        }
        function getConvertReferralRewards(address account)
            public
            view
            returns (bool)
        {
            return convertReferrals[account];
        }
        function getUnconvertedReferralRewards(address account)
            public
            view
            returns (uint256)
        {
            return unconvertedTokens[account];
        }
        function convertReferralRewards(bool convert) public {
            require(
                enableConvertingReferralRewards,
                "Converting referral rewards is not enabled yet!"
            );
            convertReferrals[msg.sender] = convert;
        }
        function updateReferralLeaderboards() private {
            // check if the daily/weekly/monthly leaderboards should be reset
            if (block.timestamp >= dailyTimer) {
                iterationDaily++;
                dailyTimer = block.timestamp + 8600;
                emit LeaderboardCompletion(1, iterationDaily - 1);
            }
            if (block.timestamp >= weeklyTimer) {
                iterationWeekly++;
                weeklyTimer = block.timestamp + 604800;
                emit LeaderboardCompletion(2, iterationWeekly - 1);
            }
            if (block.timestamp >= monthlyTimer) {
                iterationMonthly++;
                monthlyTimer = block.timestamp + 2629743;
                emit LeaderboardCompletion(3, iterationMonthly - 1);
            }
        }
        function getReferralLeaderboardTimers()
            public
            view
            returns (
                uint256,
                uint256,
                uint256
            )
        {
            return (dailyTimer, weeklyTimer, monthlyTimer);
        }
        function setReferralLeaderboardTimers(
            uint256 daily,
            uint256 weekly,
            uint256 monthly
        ) public onlyOwner {
            dailyTimer = daily;
            weeklyTimer = weekly;
            monthlyTimer = monthly;
        }
        function forceUpdateReferralLeaderboards()
            public
            onlyOwner
            returns (
                uint256,
                uint256,
                uint256
            )
        {
            updateReferralLeaderboards();
            return getReferralLeaderboardTimers();
        }
        function getIterations()
            public
            view
            returns (
                uint256,
                uint256,
                uint256,
                uint256
            )
        {
            return (iteration, iterationDaily, iterationWeekly, iterationMonthly);
        }
        function setIterations(
            uint256 newIteration,
            uint256 newIterationDaily,
            uint256 newIterationWeekly,
            uint256 newIterationMonthly
        ) public onlyOwner {
            iteration = newIteration;
            iterationDaily = newIterationDaily;
            iterationWeekly = newIterationWeekly;
            iterationMonthly = newIterationMonthly;
        }
        function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
            // approve token transfer to cover all possible scenarios
            _approve(address(this), address(uniswapV2Router), tokenAmount);
            // add the liquidity
            uniswapV2Router.addLiquidityETH{value: ethAmount}(
                address(this),
                tokenAmount,
                0, // slippage is unavoidable
                0, // slippage is unavoidable
                liquidityWallet,
                block.timestamp
            );
        }
        function forceSwapAndSendDividendsAndMarketingFundsAndLiquidity(
            uint256 dividends,
            uint256 marketing,
            uint256 liquidity
        ) public onlyOwner {
            swapAndLiquify(liquidity);
            swapAndSendDividendsAndMarketingFunds(dividends, marketing);
        }
        function swapAndSendDividendsAndMarketingFunds(
            uint256 dividends,
            uint256 marketing
        ) private {
            if (dividends + marketing > balanceOf(address(this))) {
                emit SendDividends(dividends, marketing, false);
                return;
            }
            uint256 beforeSwap;
            uint256 afterSwapDelta;
            if (dividends > swapTokensAtAmountMax) {
                dividends = swapTokensAtAmountMax;
            }
            beforeSwap = address(this).balance;
            swapTokensForEth(dividends, payable(address(this)));
            afterSwapDelta = address(this).balance - beforeSwap;
            countBNBRewardsFee -= dividends;
            uint256 BNBRewardsFeeBNB = afterSwapDelta;
            if (dividends <= 0) {
                BNBRewardsFeeBNB = 0;
            }
            (bool success, ) = address(dividendTracker).call{
                value: BNBRewardsFeeBNB
            }("");
            if (marketing > swapTokensAtAmountMax) {
                marketing = swapTokensAtAmountMax;
            }
            beforeSwap = address(this).balance;
            swapTokensForEth(marketing, payable(address(this)));
            afterSwapDelta = address(this).balance - beforeSwap;
            countDevFees -= marketing;
            uint256 devFeesBNB = afterSwapDelta;
            if (marketing <= 0) {
                devFeesBNB = 0;
            }
            // Calculate the amount to send to each wallet
            uint256 splitValue = devFeesBNB / 2;
            // Send to first wallet
            (bool successWallet1, ) = address(marketingAddress).call{
                value: splitValue
            }("");
            require(successWallet1, "Sending BNB to wallet 1 failed");
            // Send to second wallet
            (bool successWallet2, ) = address(marketingAddress2).call{
                value: splitValue
            }("");
            require(successWallet2, "Sending BNB to wallet 2 failed");
            // Check if both transfers were successful
            bool successMarketing = successWallet1 && successWallet2;
            emit SendDividends(
                BNBRewardsFeeBNB,
                devFeesBNB,
                success && successMarketing
            );
        }
        function setearlyBlocks(uint256 amount) public onlyOwner {
            require(!tradingEnabled);
            earlyBlocks = amount;
        }
        function setearlyTax(uint256 amount) public onlyOwner {
            require(!tradingEnabled);
            earlyTax = amount;
        }
    }
    contract RuffRuffDividendTracker is DividendPayingToken, Ownable {
        using SafeMath for uint256;
        using SafeMathInt for int256;
        using IterableMapping for IterableMapping.Map;
        IterableMapping.Map private tokenHoldersMap;
        uint256 public lastProcessedIndex;
        mapping(address => bool) public excludedFromDividends;
        mapping(address => bool) public excludedFromAutoClaim;
        mapping(address => bool) public autoReinvest;
        mapping(address => address) public payoutToken;
        mapping(address => bool) public allowTokens;
        bool public allowCustomTokens;
        bool public allowAutoReinvest;
        bool public dividendsPaused = false;
        IUniswapV2Router02 public uniswapV2Router;
        RuffRuff public ruffruff;
        mapping(address => uint256) public lastClaimTimes;
        uint256 public immutable minimumTokenBalanceForAutoDividends;
        uint256 public immutable minimumTokenBalanceForDividends;
        event ExcludeFromDividends(address indexed account);
        event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);
        event DividendReinvested(
            address indexed acount,
            uint256 value,
            bool indexed automatic
        );
        event Claim(
            address indexed account,
            uint256 amount,
            bool indexed automatic
        );
        event DividendsPaused(bool paused);
        event SetAllowCustomTokens(bool allow);
        event SetAllowAutoReinvest(bool allow);
        constructor(address payable mainContract)
            DividendPayingToken(
                "RuffRuff_Dividend_Tracker",
                "RuffRuff_Dividend_Tracker"
            )
        {
            ruffruff = RuffRuff(mainContract);
            minimumTokenBalanceForAutoDividends = 1 * (10**9);
            minimumTokenBalanceForDividends = 1 * (10**9);
            uniswapV2Router = IUniswapV2Router02(
                //0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D MAINNET
                0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D //TESTNET
            );
            allowCustomTokens = true;
            allowAutoReinvest = true;
        }
        function decimals() public view virtual override returns (uint8) {
            return 9;
        }
        function _transfer(
            address,
            address,
            uint256
        ) internal pure override {
            require(false, "RuffRuff_Dividend_Tracker: No transfers allowed");
        }
        function withdrawDividend() public pure override {
            require(
                false,
                "RuffRuff_Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main RuffRuff contract."
            );
        }
        function isExcludedFromAutoClaim(address account)
            external
            view
            onlyOwner
            returns (bool)
        {
            return excludedFromAutoClaim[account];
        }
        function isReinvest(address account)
            external
            view
            onlyOwner
            returns (bool)
        {
            return autoReinvest[account];
        }
        function getAllowCustomTokens() public view returns (bool) {
            return (allowCustomTokens);
        }
        function setAllowCustomTokens(bool allow) external onlyOwner {
            require(allowCustomTokens != allow);
            allowCustomTokens = allow;
            emit SetAllowCustomTokens(allow);
        }
        function setAllowAutoReinvest(bool allow) external onlyOwner {
            require(allowAutoReinvest != allow);
            allowAutoReinvest = allow;
            emit SetAllowAutoReinvest(allow);
        }
        function excludeFromDividends(address account) external onlyOwner {
            require(!excludedFromDividends[account]);
            excludedFromDividends[account] = true;
            _setBalance(account, 0);
            tokenHoldersMap.remove(account);
            emit ExcludeFromDividends(account);
        }
        function setAutoClaim(address account, bool value) external onlyOwner {
            excludedFromAutoClaim[account] = value;
        }
        function setReinvest(address account, bool value) external onlyOwner {
            autoReinvest[account] = value;
        }
        function setDividendsPaused(bool value) external onlyOwner {
            require(dividendsPaused != value);
            dividendsPaused = value;
            emit DividendsPaused(value);
        }
        function getLastProcessedIndex() external view returns (uint256) {
            return lastProcessedIndex;
        }
        function getNumberOfTokenHolders() external view returns (uint256) {
            return tokenHoldersMap.keys.length;
        }
        function getAccount(address _account)
            public
            view
            returns (
                address account,
                int256 index,
                int256 iterationsUntilProcessed,
                uint256 withdrawableDividends,
                uint256 totalDividends,
                uint256 lastClaimTime
            )
        {
            account = _account;
            index = tokenHoldersMap.getIndexOfKey(account);
            iterationsUntilProcessed = -1;
            if (index >= 0) {
                if (uint256(index) > lastProcessedIndex) {
                    iterationsUntilProcessed = index.sub(
                        int256(lastProcessedIndex)
                    );
                } else {
                    uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length >
                        lastProcessedIndex
                        ? tokenHoldersMap.keys.length.sub(lastProcessedIndex)
                        : 0;
                    iterationsUntilProcessed = index.add(
                        int256(processesUntilEndOfArray)
                    );
                }
            }
            withdrawableDividends = withdrawableDividendOf(account);
            totalDividends = accumulativeDividendOf(account);
            lastClaimTime = lastClaimTimes[account];
        }
        function getAccountAtIndex(uint256 index)
            public
            view
            returns (
                address,
                int256,
                int256,
                uint256,
                uint256,
                uint256
            )
        {
            if (index >= tokenHoldersMap.size()) {
                return (
                    0x0000000000000000000000000000000000000000,
                    -1,
                    -1,
                    0,
                    0,
                    0
                );
            }
            address account = tokenHoldersMap.getKeyAtIndex(index);
            return getAccount(account);
        }
        function setBalance(address account, uint256 newBalance)
            external
            onlyOwner
        {
            if (excludedFromDividends[account]) {
                return;
            }
            if (newBalance < minimumTokenBalanceForDividends) {
                tokenHoldersMap.remove(account);
                _setBalance(account, 0);
                return;
            }
            _setBalance(account, newBalance);
            if (newBalance >= minimumTokenBalanceForAutoDividends) {
                tokenHoldersMap.set(account, newBalance);
            } else {
                tokenHoldersMap.remove(account);
            }
        }
        function process(uint256 gas)
            public
            returns (
                uint256,
                uint256,
                uint256
            )
        {
            uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;
            if (numberOfTokenHolders == 0 || dividendsPaused) {
                return (0, 0, lastProcessedIndex);
            }
            uint256 _lastProcessedIndex = lastProcessedIndex;
            uint256 gasUsed = 0;
            uint256 gasLeft = gasleft();
            uint256 iterations = 0;
            uint256 claims = 0;
            while (gasUsed < gas && iterations < numberOfTokenHolders) {
                _lastProcessedIndex++;
                if (_lastProcessedIndex >= numberOfTokenHolders) {
                    _lastProcessedIndex = 0;
                }
                address account = tokenHoldersMap.keys[_lastProcessedIndex];
                if (!excludedFromAutoClaim[account]) {
                    if (processAccount(payable(account), true)) {
                        claims++;
                    }
                }
                iterations++;
                uint256 newGasLeft = gasleft();
                if (gasLeft > newGasLeft) {
                    gasUsed = gasUsed.add(gasLeft.sub(newGasLeft));
                }
                gasLeft = newGasLeft;
            }
            lastProcessedIndex = _lastProcessedIndex;
            return (iterations, claims, lastProcessedIndex);
        }
        function processAccount(address payable account, bool automatic)
            public
            onlyOwner
            returns (bool)
        {
            if (dividendsPaused) {
                return false;
            }
            bool reinvest = autoReinvest[account];
            if (automatic && reinvest && !allowAutoReinvest) {
                return false;
            }
            uint256 amount = reinvest
                ? _reinvestDividendOfUser(account)
                : _withdrawDividendOfUser(account);
            if (amount > 0) {
                lastClaimTimes[account] = block.timestamp;
                if (reinvest) {
                    emit DividendReinvested(account, amount, automatic);
                } else {
                    emit Claim(account, amount, automatic);
                }
                return true;
            }
            return false;
        }
        function updateUniswapV2Router(address newAddress) public onlyOwner {
            uniswapV2Router = IUniswapV2Router02(newAddress);
        }
        function updatePayoutToken(address account, address token)
            public
            onlyOwner
        {
            require(
                allowTokens[token] || token == address(0),
                "Token not in allow list"
            );
            payoutToken[account] = token;
        }
        function getPayoutToken(address account) public view returns (address) {
            return payoutToken[account];
        }
        function updateAllowTokens(address token, bool allow) public onlyOwner {
            allowTokens[token] = allow;
        }
        function getAllowTokens(address token) public view returns (bool) {
            return allowTokens[token];
        }
        function _reinvestDividendOfUser(address account)
            private
            returns (uint256)
        {
            uint256 _withdrawableDividend = withdrawableDividendOf(account);
            if (_withdrawableDividend > 0) {
                bool success;
                withdrawnDividends[account] = withdrawnDividends[account].add(
                    _withdrawableDividend
                );
                address[] memory path = new address[](2);
                path[0] = uniswapV2Router.WETH();
                path[1] = address(ruffruff);
                uint256 prevBalance = ruffruff.balanceOf(address(this));
                // make the swap
                try
                    uniswapV2Router
                        .swapExactETHForTokensSupportingFeeOnTransferTokens{
                        value: _withdrawableDividend
                    }(
                        0, // accept any amount of Tokens
                        path,
                        address(this),
                        block.timestamp
                    )
                {
                    uint256 received = ruffruff.balanceOf(address(this)).sub(
                        prevBalance
                    );
                    if (received > 0) {
                        success = true;
                        ruffruff.transfer(account, received);
                    } else {
                        success = false;
                    }
                } catch {
                    success = false;
                }
                if (!success) {
                    withdrawnDividends[account] = withdrawnDividends[account].sub(
                        _withdrawableDividend
                    );
                    return 0;
                }
                return _withdrawableDividend;
            }
            return 0;
        }
        function _withdrawDividendOfUser(address payable user)
            internal
            override
            returns (uint256)
        {
            uint256 _withdrawableDividend = withdrawableDividendOf(user);
            if (_withdrawableDividend > 0) {
                withdrawnDividends[user] = withdrawnDividends[user].add(
                    _withdrawableDividend
                );
                address tokenAddress = payoutToken[user];
                bool success;
                // if no tokenAddress assume bnb payout
                if (
                    !allowCustomTokens ||
                    tokenAddress == address(0) ||
                    !allowTokens[tokenAddress]
                ) {
                    (success, ) = user.call{
                        value: _withdrawableDividend,
                        gas: 3000
                    }("");
                } else {
                    //investor wants to be payed out in a custom token
                    address[] memory path = new address[](2);
                    path[0] = uniswapV2Router.WETH();
                    path[1] = tokenAddress;
                    try
                        uniswapV2Router
                            .swapExactETHForTokensSupportingFeeOnTransferTokens{
                            value: _withdrawableDividend
                        }(
                            0, // accept any amount of Tokens
                            path,
                            user,
                            block.timestamp
                        )
                    {
                        success = true;
                    } catch {
                        success = false;
                    }
                }
                if (!success) {
                    withdrawnDividends[user] = withdrawnDividends[user].sub(
                        _withdrawableDividend
                    );
                    return 0;
                } else {
                    emit DividendWithdrawn(user, _withdrawableDividend);
                }
                return _withdrawableDividend;
            }
            return 0;
        }
    }