Silver Pure Reserve (SLVX)

Description:

Smart contract deployed on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

/// @title Silver Pure Reserve (SLVX)
/// @notice Token ERC20 representando 1 onza troy de plata pura (999), con supply inicial de 6 mil millones.
///         Incluye freeze, burn, mint, transfer ownership en 2 pasos, nonReentrancy, EIP-2612 permit.

contract SilverPureReserve {
    string public constant name = "Silver Pure Reserve";
    string public constant symbol = "SLVX";
    uint8 public constant decimals = 18;

    uint256 public totalSupply;
    uint256 public constant INITIAL_SUPPLY = 6_000_000_000 * 1e18;

    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;
    mapping(address => bool) public frozen;

    address public owner;
    address public pendingOwner;
    address public compliance;

    uint256 private _entered;

    // EIP-2612 permit
    mapping(address => uint256) public nonces;
    bytes32 public DOMAIN_SEPARATOR;
    bytes32 public constant PERMIT_TYPEHASH = keccak256(
        "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
    );

    // Events
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event ComplianceTransferred(address indexed previousCompliance, address indexed newCompliance);
    event AddressFrozen(address indexed account, bool frozen);
    event Mint(address indexed to, uint256 amount);
    event Burn(address indexed from, uint256 amount);

    // Modifiers
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    modifier onlyCompliance() {
        require(msg.sender == compliance, "Not compliance");
        _;
    }

    modifier notFrozen(address account) {
        require(!frozen[account], "Address frozen");
        _;
    }

    modifier nonReentrant() {
        require(_entered == 0, "ReentrancyGuard: reentrant call");
        _entered = 1;
        _;
        _entered = 0;
    }

    constructor() {
        owner = msg.sender;
        compliance = msg.sender;

        totalSupply = INITIAL_SUPPLY;
        balanceOf[msg.sender] = INITIAL_SUPPLY;
        emit Transfer(address(0), msg.sender, INITIAL_SUPPLY);

        uint256 chainId;
        assembly {
            chainId := chainid()
        }

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name)),
                keccak256(bytes("1")),
                chainId,
                address(this)
            )
        );
    }

    // ===== ERC-20 Standard =====
    function transfer(address to, uint256 value) external notFrozen(msg.sender) notFrozen(to) returns (bool) {
        require(to != address(0), "Zero address");
        require(balanceOf[msg.sender] >= value, "Insufficient balance");

        unchecked {
            balanceOf[msg.sender] -= value;
            balanceOf[to] += value;
        }

        emit Transfer(msg.sender, to, value);
        return true;
    }

    function approve(address spender, uint256 value) external notFrozen(msg.sender) notFrozen(spender) returns (bool) {
        require(spender != address(0), "Zero address");

        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value)
        external
        notFrozen(msg.sender)
        notFrozen(from)
        notFrozen(to)
        nonReentrant
        returns (bool)
    {
        require(to != address(0), "Zero address");
        require(balanceOf[from] >= value, "Insufficient balance");
        require(allowance[from][msg.sender] >= value, "Allowance exceeded");

        unchecked {
            allowance[from][msg.sender] -= value;
            balanceOf[from] -= value;
            balanceOf[to] += value;
        }

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

    function increaseAllowance(address spender, uint256 addedValue)
        external
        notFrozen(msg.sender)
        notFrozen(spender)
        returns (bool)
    {
        require(spender != address(0), "Zero address");

        allowance[msg.sender][spender] += addedValue;
        emit Approval(msg.sender, spender, allowance[msg.sender][spender]);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue)
        external
        notFrozen(msg.sender)
        notFrozen(spender)
        returns (bool)
    {
        require(spender != address(0), "Zero address");

        uint256 current = allowance[msg.sender][spender];
        allowance[msg.sender][spender] = subtractedValue >= current ? 0 : current - subtractedValue;
        emit Approval(msg.sender, spender, allowance[msg.sender][spender]);
        return true;
    }

    // ===== Mint / Burn =====
    function mint(address to, uint256 amount) external onlyOwner nonReentrant {
        require(to != address(0), "Zero address");

        totalSupply += amount;
        balanceOf[to] += amount;

        emit Mint(to, amount);
        emit Transfer(address(0), to, amount);
    }

    function burn(address from, uint256 amount) external onlyOwner nonReentrant {
        require(from != address(0), "Zero address");
        require(balanceOf[from] >= amount, "Insufficient balance");

        unchecked {
            balanceOf[from] -= amount;
            totalSupply -= amount;
        }

        emit Burn(from, amount);
        emit Transfer(from, address(0), amount);
    }

    function burnFrom(address from, uint256 amount) external notFrozen(msg.sender) notFrozen(from) nonReentrant {
        require(from != address(0), "Zero address");
        require(balanceOf[from] >= amount, "Insufficient balance");
        require(allowance[from][msg.sender] >= amount, "Allowance exceeded");

        unchecked {
            allowance[from][msg.sender] -= amount;
            balanceOf[from] -= amount;
            totalSupply -= amount;
        }

        emit Burn(from, amount);
        emit Transfer(from, address(0), amount);
    }

    // ===== Freeze Accounts =====
    function setFrozen(address account, bool isFrozen) external onlyCompliance {
        frozen[account] = isFrozen;
        emit AddressFrozen(account, isFrozen);
    }

    // ===== Ownership Control =====
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "Zero address");
        pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner, newOwner);
    }

    function acceptOwnership() external {
        require(msg.sender == pendingOwner, "Not pending owner");
        emit OwnershipTransferred(owner, pendingOwner);
        owner = pendingOwner;
        pendingOwner = address(0);
    }

    function setCompliance(address newCompliance) external onlyOwner {
        require(newCompliance != address(0), "Zero address");
        emit ComplianceTransferred(compliance, newCompliance);
        compliance = newCompliance;
    }

    // ===== EIP-2612 Permit =====
    function permit(
        address owner_,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(deadline >= block.timestamp, "Permit expired");

        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(
                    PERMIT_TYPEHASH,
                    owner_,
                    spender,
                    value,
                    nonces[owner_]++,
                    deadline
                ))
            )
        );

        address recoveredAddress = ecrecover(digest, v, r, s);
        require(recoveredAddress == owner_, "Invalid signature");

        allowance[owner_][spender] = value;
        emit Approval(owner_, spender, value);
    }
}

Tags:
addr:0x33e0ffb16189024724a86a5dfeb6fc6b2514cbf4|verified:true|block:23629506|tx:0xe2c0e7065ddddf12a01195a8bc8d77ad1d332d1ef67c73303e9e8e2159936d60|first_check:1761232154

Submitted on: 2025-10-23 17:09:17

Comments

Log in to comment.

No comments yet.