Sonic Blaze Testnet

Contract Diff Checker

Contract Name:
DappToken

Contract Source Code:

pragma solidity 0.8.28;

// SPDX-License-Identifier: Unlicensed

contract DappToken {
    string public name = "Sonic Test Token";
    string public symbol = "STT";
    string public standard = "Sonic Test Token v1.0";
    uint256 private _totalSupply;
    uint256 public decimals = 18;

    address public immutable owner;
    address public liquidityPool;

    // Distribution tracking
    uint256 public taxPool;
    uint256 public lastDistribution;
    uint256 public constant DISTRIBUTION_INTERVAL = 5 minutes;
    uint256 public reflectionFee = 5; // Default 5% fee

    // Reflection system
    uint256 private constant POINT_MULTIPLIER = 10 ** 18;
    uint256 private totalDividendPoints;
    uint256 private unclaimedDividends;
    uint256 private blackListAmount;

    // Add new variables for tax distribution
    uint256 private constant TAX_DENOMINATOR = 100;
    uint256 private lastTaxDistribution;

    struct Account {
        uint256 balance;
        uint256 lastDividendPoints;
    }

    // State variables
    mapping(address => Account) public accounts;
    mapping(address => mapping(address => uint256)) public allowance;
    mapping(address => bool) private _isExcluded;
    mapping(address => bool) private isBlackListed;

    // Native token distribution tracking
    uint256 private nativeTokenPool;

    // Holder tracking
    address[] private holders;
    mapping(address => bool) private isHolder;

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    event RewardsDistributed(uint256 amount);
    event LiquidityPoolSet(address indexed newPool);
    event BlacklistUpdated(address indexed user, bool isBlacklisted);
    event NativeTokensReceived(uint256 amount);
    event NativeTokensDistributed(address indexed holder, uint256 amount);

    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call");
        _;
    }

    modifier updateAccount(address account) {
        uint256 owing = dividendsOwing(account);
        if (owing > 0) {
            unclaimedDividends -= owing;
            accounts[account].balance += owing;
        }
        accounts[account].lastDividendPoints = totalDividendPoints;
        _;
    }

    constructor() {
        owner = msg.sender;
        _totalSupply = 1000000000000000;
        accounts[msg.sender].balance = _totalSupply;
        _isExcluded[msg.sender] = true;
        lastDistribution = block.timestamp;
        emit Transfer(address(0), msg.sender, _totalSupply);
    }

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    function _transfer(address _from, address _to, uint256 _value) 
        internal 
        updateAccount(_from) 
        updateAccount(_to) 
    {
        // Determine transaction type
        bool isBuy = _from == liquidityPool;
        bool isSell = _to == liquidityPool;

        uint256 currentFee;
        // Apply 5% tax only on buy/sell transactions
        if (_isExcluded[_from]) {
            currentFee = 0;
        } else {
            currentFee = (isBuy || isSell) ? reflectionFee : 0;
        }

        uint256 rAmount = (_value * currentFee) / TAX_DENOMINATOR;
        uint256 amount = _value - rAmount;

        // Update balances
        accounts[_from].balance -= _value;
        accounts[_to].balance += amount;

        // Accumulate taxes and update dividend points
        if (rAmount > 0) {
            // Update dividend points when tax is collected
            uint256 totalCirculating = _totalSupply - blackListAmount;
            if (totalCirculating > 0) {
                totalDividendPoints += (rAmount * POINT_MULTIPLIER) / totalCirculating;
                unclaimedDividends += rAmount;
            }
        }

        // Update blacklist tracking
        if (isBlackListed[_from]) {
            blackListAmount -= _value;
        }
        if (isBlackListed[_to]) {
            blackListAmount += amount;
        }

        // Track holders for native token distribution
        if (accounts[_to].balance == 0 && amount > 0) {
            _addHolder(_to);
        }

        emit Transfer(_from, _to, amount);
    }

    // Add this new function to set liquidity pool address
    function setLiquidityPool(address _pool) external onlyOwner {
        require(_pool != address(0), "Invalid pool address");
        liquidityPool = _pool;
        _isExcluded[_pool] = true;
        emit LiquidityPoolSet(_pool);
    }

    // Modified distribution function with time-based triggering
    function distributeRewards() external {
        require(
            block.timestamp >= lastDistribution + DISTRIBUTION_INTERVAL,
            "Must wait 5 minutes between distributions"
        );
        require(unclaimedDividends > 0 || nativeTokenPool > 0, "No rewards to distribute");

        // Distribute token rewards first
        if (unclaimedDividends > 0) {
            _distributeTaxedTokens();
        }

        // Then distribute native tokens
        if (nativeTokenPool > 0) {
            distributeNativeTokens();
        }

        lastDistribution = block.timestamp;
    }

    function _distributeTaxedTokens() private {
        uint256 totalCirculating = _totalSupply - blackListAmount;
        require(totalCirculating > 0, "No eligible holders");
        
        for (uint256 i = 0; i < holders.length; i++) {
            address holder = holders[i];
            if (!isBlackListed[holder] && !_isExcluded[holder]) {
                uint256 owing = dividendsOwing(holder);
                if (owing > 0) {
                    accounts[holder].balance += owing;
                    unclaimedDividends -= owing;
                    emit RewardsDistributed(owing);
                }
            }
        }
    }

    function distributeNativeTokens() private {
        uint256 totalCirculating = _totalSupply - blackListAmount;
        require(totalCirculating > 0, "No eligible holders");
        
        for (uint256 i = 0; i < holders.length; i++) {
            address holder = holders[i];
            if (!isBlackListed[holder] && !_isExcluded[holder]) {
                uint256 share = (accounts[holder].balance * nativeTokenPool) / totalCirculating;
                if (share > 0) {
                    (bool success, ) = holder.call{value: share}("");
                    require(success, "Native token transfer failed");
                    emit NativeTokensDistributed(holder, share);
                }
            }
        }
        nativeTokenPool = 0;
    }

    // Keep existing functions below (unchanged from original except for context) */
    function transfer(address _to, uint256 _value) public returns (bool) {
        require(accounts[msg.sender].balance >= _value);
        _transfer(msg.sender, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) public returns (bool) {
        allowance[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_value <= accounts[_from].balance);
        require(_value <= allowance[_from][msg.sender]);
        allowance[_from][msg.sender] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }

    function dividendsOwing(address account) internal view returns (uint256) {
        if (isBlackListed[account]) return 0;
        uint256 newDividendPoints = totalDividendPoints - accounts[account].lastDividendPoints;
        return (accounts[account].balance * newDividendPoints) / POINT_MULTIPLIER;
    }

    function balanceOf(address account) public view returns (uint256) {
        uint256 owing = dividendsOwing(account);
        return accounts[account].balance + owing;
    }

    function mint(address recipient, uint256 amount) public onlyOwner updateAccount(recipient) {
        accounts[recipient].balance += amount;
        _totalSupply += amount;
    }

    function blackList(address user) public onlyOwner updateAccount(user) {
        require(user != address(0), "Invalid address");
        require(user != owner, "Cannot blacklist owner");
        if (!isBlackListed[user]) {
            isBlackListed[user] = true;
            blackListAmount += accounts[user].balance;
            emit BlacklistUpdated(user, true);
        }
    }

    function unBlackList(address user) public onlyOwner updateAccount(user) {
        require(user != address(0), "Invalid address");
        if (isBlackListed[user]) {
            isBlackListed[user] = false;
            blackListAmount -= accounts[user].balance;
            emit BlacklistUpdated(user, false);
        }
    }

    // Add function to update reflection fee
    function setReflectionFee(uint256 _fee) external onlyOwner {
        require(_fee <= 10, "Fee cannot exceed 10%");
        reflectionFee = _fee;
    }

    function _addHolder(address account) private {
        if (!isHolder[account] && account != address(0) && account != liquidityPool) {
            holders.push(account);
            isHolder[account] = true;
        }
    }

    // Function to receive native tokens
    receive() external payable {
        nativeTokenPool += msg.value;
        emit NativeTokensReceived(msg.value);
    }
}

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

Context size (optional):