Contract Diff Checker

Contract Name:
ERC20

Contract Source Code:

File 1 of 1 : ERC20

contract ERC20 {
    // Token metadata
    string public name;
    string public symbol;
    uint8 public constant decimals = 6;
    uint256 public totalSupply = 1_000_000_000 * 10 ** 6; // 1 billion tokens

    // Token balances and allowances
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    // Factory and owner management
    address public factoryAddress;
    address private _owner;
    bool public launched;

    // Efficient account tracking
    mapping(address => uint256) private accountIndex;
    address[] public accountsWithBalance;

    // Events
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Burn(address indexed burner, uint256 value);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    // Modifiers
    modifier onlyOwner() {
        require(msg.sender == _owner, "Ownable: caller is not the owner");
        _;
    }

    constructor(string memory _name, string memory _symbol, address _factory) {
        name = _name;
        symbol = _symbol;
        factoryAddress = _factory;
        balanceOf[_factory] = totalSupply;

        _addAccount(_factory);

        emit Transfer(address(0), _factory, totalSupply);

        _owner = _factory;
        emit OwnershipTransferred(address(0), _owner);

        launched = false;
    }

    // Ownership functions
    function owner() public view returns (address) {
        return _owner;
    }

    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }

    function launch() external onlyOwner {
        require(!launched, "Token has already been launched");
        launched = true;
        renounceOwnership();
    }

    // Transfer helper functions
    function _transferAllowed(address from, address to) private view returns (bool) {
        if (launched) return true;
        if (from == owner() || to == owner()) return true;
        if (isContract(from) || isContract(to)) return false;
        return true;
    }

    function isContract(address account) internal view returns (bool) {
        return account.code.length > 0;
    }

    // ERC20 core functions
    function transfer(address to, uint256 value) external returns (bool) {
        require(_transferAllowed(msg.sender, to), "Transfer not allowed");
        return _transfer(msg.sender, to, value);
    }

    function approve(address spender, uint256 value) external returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        require(_transferAllowed(from, to), "Transfer not allowed");
        if (msg.sender != _owner) {
            require(value <= allowance[from][msg.sender], "Insufficient allowance");
            allowance[from][msg.sender] -= value;
        }
        return _transfer(from, to, value);
    }

    function _transfer(address from, address to, uint256 value) internal returns (bool) {
        require(value <= balanceOf[from], "Insufficient balance");

        balanceOf[from] -= value;
        balanceOf[to] += value;

        if (balanceOf[to] == value) {
            _addAccount(to);
        }
        if (balanceOf[from] == 0) {
            _removeAccount(from);
        }

        emit Transfer(from, to, value);
        return true;
    }

    function burn(uint256 value) external returns (bool) {
        require(value > 0, "Burn amount must be greater than zero");
        require(balanceOf[msg.sender] >= value, "Insufficient balance for burn");

        balanceOf[msg.sender] -= value;
        totalSupply -= value;

        if (balanceOf[msg.sender] == 0) {
            _removeAccount(msg.sender);
        }

        emit Transfer(msg.sender, address(0), value);
        emit Burn(msg.sender, value);
        return true;
    }

    // Account tracking functions
    function _addAccount(address account) internal {
        if (accountIndex[account] == 0) {
            accountsWithBalance.push(account);
            accountIndex[account] = accountsWithBalance.length;
        }
    }

    function _removeAccount(address account) internal {
        uint256 index = accountIndex[account];
        if (index != 0) {
            uint256 lastIndex = accountsWithBalance.length;
            if (index != lastIndex) {
                address lastAccount = accountsWithBalance[lastIndex - 1];
                accountsWithBalance[index - 1] = lastAccount;
                accountIndex[lastAccount] = index;
            }
            accountsWithBalance.pop();
            delete accountIndex[account];
        }
    }

    function getAccountCount() external view returns (uint256) {
        return accountsWithBalance.length;
    }

    function getAccountAtIndex(uint256 index) external view returns (address) {
        require(index < accountsWithBalance.length, "Index out of bounds");
        return accountsWithBalance[index];
    }
}

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

Context size (optional):