S Price: $0.736272 (-8.83%)

Contract Diff Checker

Contract Name:
Test3

Contract Source Code:

File 1 of 1 : Test3

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

/* ────────────────────────────────────────────────────────────── */
/*                          CONTEXT & OWNABLE                        */
/* ────────────────────────────────────────────────────────────── */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }
    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
contract Ownable is Context {
    address private _owner;
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    constructor () {
        _owner = _msgSender();
        emit OwnershipTransferred(address(0), _owner);
    }
    function owner() public view returns (address) {
        return _owner;
    }
    modifier onlyOwner() {
        require(_msgSender() == _owner, "Ownable: caller is not the owner");
        _;
    }
    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is zero");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }
}

/* ────────────────────────────────────────────────────────────── */
/*                        ERC20 INTERFACES & IMPLEMENTATION          */
/* ────────────────────────────────────────────────────────────── */
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 {
    mapping(address => uint256) internal _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    uint256 internal _totalSupply;
    string private _name;
    string private _symbol;
    constructor(string memory name_, string memory symbol_) {
        _name   = name_;
        _symbol = symbol_;
    }
    function name() public view override returns (string memory) { return _name; }
    function symbol() public view override returns (string memory) { return _symbol; }
    function decimals() public pure override returns (uint8) { return 18; }
    function totalSupply() public view override returns (uint256) { return _totalSupply; }
    function balanceOf(address account) public view override returns (uint256) { return _balances[account]; }
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(_msgSender(), recipient, amount); 
        return true;
    }
    function allowance(address owner, address spender) public view override returns (uint256) {
        return _allowances[owner][spender];
    }
    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount); 
        return true;
    }
    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        _transfer(sender, recipient, amount);
        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer exceeds allowance");
        unchecked { _approve(sender, _msgSender(), currentAllowance - amount); }
        return true;
    }
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); }
        return true;
    }
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0) && recipient != address(0), "ERC20: zero address");
        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: insufficient balance");
        unchecked { _balances[sender] = senderBalance - amount; }
        _balances[recipient] += amount;
        emit Transfer(sender, recipient, amount);
    }
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to zero");
        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0) && spender != address(0), "ERC20: zero address");
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
}

/* ────────────────────────────────────────────────────────────── */
/*                           SAFE MATH LIBRARIES                       */
/* ────────────────────────────────────────────────────────────── */
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); 
        return a - b;
    }
    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); 
        return a / b;
    }
    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;
    }
}
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), "SafeMathInt: multiplication overflow");
        require(b == 0 || c / b == a, "SafeMathInt: multiplication overflow");
        return c;
    }
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != -1 || a != MIN_INT256, "SafeMathInt: division overflow");
        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), "SafeMathInt: subtraction overflow");
        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), "SafeMathInt: addition overflow");
        return c;
    }
    function abs(int256 a) internal pure returns (int256) {
        require(a != MIN_INT256, "SafeMathInt: abs overflow");
        return a < 0 ? -a : a;
    }
    function toUint256Safe(int256 a) internal pure returns (uint256) {
        require(a >= 0, "SafeMathInt: negative to uint");
        return uint256(a);
    }
}
library SafeMathUint {
    function toInt256Safe(uint256 a) internal pure returns (int256) {
        int256 b = int256(a); require(b >= 0, "SafeMathUint: overflow");
        return b;
    }
}

/* ────────────────────────────────────────────────────────────── */
/*          Uniswap V2 FACTORY & ROUTER INTERFACES (SONIC)       */
/* ────────────────────────────────────────────────────────────── */
/*
    NOTE: The key fix is using WETH() instead of WSONIC().
*/
interface IUniswapV2Factory {
    function createPair(address tokenA, address tokenB) external returns (address pair);
}
interface IUniswapV2Router02 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);  // <--- Use WETH instead of WSONIC
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
         uint256 tokenAmount, 
         uint256 minETH, 
         address[] calldata path, 
         address to, 
         uint256 deadline
    ) external;
    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
         uint256 tokenAmount, 
         uint256 minTokens, 
         address[] calldata path, 
         address to, 
         uint256 deadline
    ) external;
}

/* ────────────────────────────────────────────────────────────── */
/*                      DIVIDEND TRACKER CONTRACT                   */
/* ────────────────────────────────────────────────────────────── */
contract DividendTracker is Ownable {
    using SafeMathInt for int256;
    using SafeMath for uint256;
    
    uint256 constant internal magnitude = 2**128;
    address public rewardToken;
    uint256 public magnifiedDividendPerShare;
    mapping(address => uint256) public holderBalance;
    uint256 public totalBalance;
    mapping(address => int256) public magnifiedDividendCorrections;
    mapping(address => uint256) public withdrawnDividends;
    
    event DividendsDistributed(address indexed from, uint256 amount);
    event DividendClaimed(address indexed account, uint256 amount);
    
    constructor(address _rewardToken) {
        rewardToken = _rewardToken;
    }
    function distributeDividends(uint256 amount) external onlyOwner {
        require(totalBalance > 0, "DividendTracker: no holders");
        magnifiedDividendPerShare = magnifiedDividendPerShare.add( amount.mul(magnitude).div(totalBalance) );
        emit DividendsDistributed(msg.sender, amount);
    }
    function setBalance(address account, uint256 newBalance) external onlyOwner {
        uint256 current = holderBalance[account];
        holderBalance[account] = newBalance;
        if(newBalance > current) {
            uint256 inc = newBalance.sub(current);
            magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account].sub(
                int256(magnifiedDividendPerShare.mul(inc))
            );
            totalBalance = totalBalance.add(inc);
        } else if(newBalance < current) {
            uint256 dec = current.sub(newBalance);
            magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account].add(
                int256(magnifiedDividendPerShare.mul(dec))
            );
            totalBalance = totalBalance.sub(dec);
        }
    }
    function withdrawableDividendOf(address account) public view returns (uint256) {
        int256 accumulative = int256(holderBalance[account].mul(magnifiedDividendPerShare))
            + magnifiedDividendCorrections[account];
        if(accumulative < 0) return 0;
        uint256 totalAccumulated = uint256(accumulative) / magnitude;
        if(totalAccumulated <= withdrawnDividends[account]) return 0;
        return totalAccumulated.sub(withdrawnDividends[account]);
    }
    function processAccount(address account) external onlyOwner returns (uint256) {
        uint256 amount = withdrawableDividendOf(account);
        if(amount > 0) {
            withdrawnDividends[account] = withdrawnDividends[account].add(amount);
            IERC20(rewardToken).transfer(account, amount);
            emit DividendClaimed(account, amount);
        }
        return amount;
    }
}

/* ────────────────────────────────────────────────────────────── */
/*                   MAIN TOKEN CONTRACT: TEST3                      */
/* ────────────────────────────────────────────────────────────── */
contract Test3 is ERC20, Ownable {
    using SafeMath for uint256;
    
    IUniswapV2Router02 public UniswapV2Router;
    address public UniswapV2Pair;
    
    // Tax wallet for marketing funds.
    address public taxWallet;
    // Reward token (wSONIC) for dividends.
    address public rewardToken;
    // Dividend tracker instance.
    DividendTracker public dividendTracker;
    
    // Limits and thresholds.
    uint256 public maxWallet;
    uint256 public swapTokensAtAmount;
    bool public limitsInEffect = true;
    
    bool private swapping;
    
    // Fee structure (in basis points out of 1000):
    uint256 public rewardsFeeBuy = 30;  // 3%
    uint256 public taxFeeBuy = 20;      // 2%
    uint256 public totalBuyFees = 50;   // 5%
    
    uint256 public rewardsFeeSell = 30; // 3%
    uint256 public taxFeeSell = 20;     // 2%
    uint256 public totalSellFees = 50;  // 5%
    
    // Accumulated fee counters.
    uint256 public tokensForRewards;
    uint256 public tokensForTax;
    
    // Mapping to track fee exclusion.
    mapping(address => bool) private _isExcludedFromFees;
    
    constructor() ERC20("Test4", "TEST4") {
        uint256 totalSupply = 1 * 1e6 * 1e18;  // 1,000,000 supply, example
        _mint(msg.sender, totalSupply);
        
        // Set max wallet to 2% of supply.
        maxWallet = totalSupply.mul(2).div(100);
        // Set swap threshold to 0.2% of supply.
        swapTokensAtAmount = totalSupply.mul(2).div(1000);
        
        // Set initial tax wallet to deployer.
        taxWallet = msg.sender;
        // Hardcode the reward token to wSONIC (the actual address).
        rewardToken = 0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38;
        
        // Initialize dividend tracker.
        dividendTracker = new DividendTracker(rewardToken);
        
        // Initialize router & pair - using WETH() instead of WSONIC().
        UniswapV2Router = IUniswapV2Router02(0x95a7e403d7cF20F675fF9273D66e94d35ba49fA3);
        UniswapV2Pair = IUniswapV2Factory(UniswapV2Router.factory())
            .createPair(address(this), UniswapV2Router.WETH());
        
        // Exclude owner and contract from fees.
        _isExcludedFromFees[owner()] = true;
        _isExcludedFromFees[address(this)] = true;
    }
    
    /* ───────────────────────── ADMIN FUNCTIONS ───────────────────────── */
    function claim() external {
        dividendTracker.processAccount(msg.sender);
    }
    function removeLimits() external onlyOwner {
        limitsInEffect = false;
    }
    function updateBuyFees(uint256 _newRewardsFeeBuy, uint256 _newTaxFeeBuy) external onlyOwner {
        rewardsFeeBuy = _newRewardsFeeBuy;
        taxFeeBuy = _newTaxFeeBuy;
        totalBuyFees = _newRewardsFeeBuy + _newTaxFeeBuy;
        require(totalBuyFees <= 100, "Buy fees too high");
    }
    function updateSellFees(uint256 _newRewardsFeeSell, uint256 _newTaxFeeSell) external onlyOwner {
        rewardsFeeSell = _newRewardsFeeSell;
        taxFeeSell = _newTaxFeeSell;
        totalSellFees = _newRewardsFeeSell + _newTaxFeeSell;
        require(totalSellFees <= 100, "Sell fees too high");
    }
    function updateMaxWalletAmount(uint256 newMaxWallet) external onlyOwner {
        maxWallet = newMaxWallet;
    }
    function updateTaxWallet(address newTaxWallet) external onlyOwner {
        require(newTaxWallet != address(0), "Zero address");
        taxWallet = newTaxWallet;
    }
    function updateRewardToken(address newRewardToken) external onlyOwner {
        require(newRewardToken != address(0), "Zero address");
        rewardToken = newRewardToken;
        dividendTracker = new DividendTracker(newRewardToken);
    }
    function updateRouter(address newRouter) external onlyOwner {
        require(newRouter != address(0), "Zero address");
        UniswapV2Router = IUniswapV2Router02(newRouter);
        UniswapV2Pair = IUniswapV2Factory(UniswapV2Router.factory())
            .createPair(address(this), UniswapV2Router.WETH());
    }
    function excludeFromFees(address account, bool excluded) external onlyOwner {
        _isExcludedFromFees[account] = excluded;
    }
    function excludeMultipleAccountsFromFees(address[] calldata accounts, bool excluded) external onlyOwner {
        for (uint256 i = 0; i < accounts.length; i++) {
            _isExcludedFromFees[accounts[i]] = excluded;
        }
    }
    
    /* ───────────────────── CORE TRANSFER & FEE LOGIC ───────────────────── */
    // Trading is always enabled.
    function _transfer(address from, address to, uint256 amount) internal override {
        // Enforce max wallet if limits are active (except for pair and owner).
        if(limitsInEffect && to != UniswapV2Pair && to != owner()) {
            require(balanceOf(to).add(amount) <= maxWallet, "Exceeds max wallet");
        }
        
        uint256 fees = 0;
        if(!swapping && !_isExcludedFromFees[from] && !_isExcludedFromFees[to] && from != owner() && to != owner()){
            if(from == UniswapV2Pair) { // Buy
                fees = amount.mul(totalBuyFees).div(1000);
                tokensForRewards = tokensForRewards.add(fees.mul(rewardsFeeBuy).div(totalBuyFees));
                tokensForTax = tokensForTax.add(fees.mul(taxFeeBuy).div(totalBuyFees));
            } else if(to == UniswapV2Pair) { // Sell
                fees = amount.mul(totalSellFees).div(1000);
                tokensForRewards = tokensForRewards.add(fees.mul(rewardsFeeSell).div(totalSellFees));
                tokensForTax = tokensForTax.add(fees.mul(taxFeeSell).div(totalSellFees));
            }
        }
        if(fees > 0) {
            super._transfer(from, address(this), fees);
            amount = amount.sub(fees);
        }
        super._transfer(from, to, amount);
        
        // Update dividend tracker balances.
        dividendTracker.setBalance(from, balanceOf(from));
        dividendTracker.setBalance(to, balanceOf(to));
        
        // Auto-process dividends for both sender and recipient.
        if(!swapping) {
            swapping = true;
            dividendTracker.processAccount(from);
            dividendTracker.processAccount(to);
            swapping = false;
        }
        
        // If the contract's token balance exceeds the swap threshold and the transfer is not a buy, trigger swapBack.
        if(!swapping && balanceOf(address(this)) >= swapTokensAtAmount && from != UniswapV2Pair) {
            swapBack();
        }
    }
    
    /* ───────────────────── SWAP & DIVIDEND PROCESSING ───────────────────── */
    function swapBack() private {
        swapping = true;
        uint256 contractBalance = balanceOf(address(this));
        uint256 totalTokensToSwap = tokensForRewards.add(tokensForTax);
        if(contractBalance == 0 || totalTokensToSwap == 0) { swapping = false; return; }
        
        uint256 taxPortion = tokensForTax;
        uint256 rewardsPortion = tokensForRewards;
        tokensForTax = 0;
        tokensForRewards = 0;
        
        // Swap tax portion for ETH and send to tax wallet.
        swapTokensForEth(taxPortion);
        (bool sent, ) = taxWallet.call{value: address(this).balance}("");
        require(sent, "ETH transfer failed");
        
        // Swap rewards portion for the reward token and distribute dividends.
        uint256 initialRewardBal = IERC20(rewardToken).balanceOf(address(this));
        swapTokensForReward(rewardsPortion);
        uint256 newRewardBal = IERC20(rewardToken).balanceOf(address(this)).sub(initialRewardBal);
        if(newRewardBal > 0) {
            dividendTracker.distributeDividends(newRewardBal);
        }
        swapping = false;
    }
    function swapTokensForEth(uint256 tokenAmount) private {
        address[] memory path = new address[](2);
        path[0] = address(this);
        // Use WETH() instead of WSONIC()
        path[1] = UniswapV2Router.WETH();
        
        _approve(address(this), address(UniswapV2Router), tokenAmount);
        UniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0,
            path,
            address(this),
            block.timestamp
        );
    }
    function swapTokensForReward(uint256 tokenAmount) private {
        address[] memory path = new address[](3);
        path[0] = address(this);
        // Use WETH() instead of WSONIC()
        path[1] = UniswapV2Router.WETH();
        path[2] = rewardToken;
        
        _approve(address(this), address(UniswapV2Router), tokenAmount);
        UniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            tokenAmount,
            0,
            path,
            address(this),
            block.timestamp
        );
    }
    
    // Allow the contract to receive ETH from swaps.
    receive() external payable {}
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):