CMTDE V2 Token (CMTDE_V2)

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

/**
 * @title IERC20
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, 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 from, address to, 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);
}

/**
 * @title IERC20Metadata
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
}

/**
 * @title AggregatorV3Interface
 * @notice Chainlink Price Feed Interface
 */
interface AggregatorV3Interface {
    function decimals() external view returns (uint8);
    function description() external view returns (string memory);
    function version() external view returns (uint256);
    function getRoundData(uint80 _roundId)
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}

/**
 * @title CMTDE V2 Token Contract - Fully ERC-20 Compliant
 * @dev Gold-backed token with full ERC-20 compliance and enhanced features
 */
contract CMTDE_V2 is IERC20, IERC20Metadata {
    
    // State variables
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    
    uint256 private _totalSupply;
    uint256 private _goldReserves;
    address public owner;
    bool public paused = false;
    
    // Security parameters - FIXED BOUNDS
    uint256 public constant MAX_MINT_PER_TX = 1000000 * 10**18; // 1M tokens max per tx
    uint256 public constant MAX_DAILY_MINT = 10000000 * 10**18; // 10M tokens per day
    uint256 public constant PRICE_STALENESS_THRESHOLD = 3600; // 1 hour
    uint256 public constant MIN_GOLD_PRICE = 50 * 10**8; // $50 minimum (very safe)
    uint256 public constant MAX_GOLD_PRICE = 10000 * 10**8; // $10000 maximum
    
    // Purchase parameters
    uint256 public constant MAX_PURCHASE_PER_TX = 500000 * 10**18; // 500K tokens max per purchase
    uint256 public constant MAX_DAILY_PURCHASE = 5000000 * 10**18; // 5M tokens per day
    uint256 public constant MIN_PURCHASE_ETH = 0.001 ether; // Minimum 0.001 ETH purchase
    uint256 public constant MAX_PURCHASE_ETH = 100 ether; // Maximum 100 ETH purchase
    
    // Sell parameters
    uint256 public constant MAX_SELL_PER_TX = 250000 * 10**18; // 250K tokens max per sell
    uint256 public constant MAX_DAILY_SELL = 2500000 * 10**18; // 2.5M tokens per day
    uint256 public constant MIN_SELL_TOKENS = 100 * 10**18; // Minimum 100 tokens to sell
    uint256 public constant MIN_CONTRACT_BALANCE = 1 ether; // Minimum contract balance to maintain
    
    uint256 public dailyMintAmount;
    uint256 public lastMintResetTime;
    uint256 public dailyPurchaseAmount;
    uint256 public lastPurchaseResetTime;
    uint256 public dailySellAmount;
    uint256 public lastSellResetTime;
    
    // Purchase and Sell settings
    bool public purchaseEnabled = true;
    bool public sellEnabled = true;
    uint256 public priceMarkup = 105; // 5% markup over gold price for buying (105/100 = 1.05)
    uint256 public priceDiscount = 95; // 5% discount under gold price for selling (95/100 = 0.95)
    
    // Oracle setup
    AggregatorV3Interface internal goldPriceFeed;
    AggregatorV3Interface internal backupPriceFeed;
    uint256 private constant PRICE_DECIMALS = 8;
    uint256 private constant TOKEN_DECIMALS = 18;
    
    // Manual price override
    bool public manualPriceEnabled = false;
    uint256 public manualGoldPrice;
    uint256 public manualPriceTimestamp;
    
    // Token metadata
    string private _name = "CMTDE V2 Token";
    string private _symbol = "CMTDE_V2";
    uint8 private _decimals = 18;

    // Events (keeping existing ones and ensuring ERC-20 compliance)
    event Mint(address indexed to, uint256 value);
    event Burn(address indexed from, uint256 value);
    event Paused();
    event Unpaused();
    event PriceFeedUpdated(address newPriceFeed);
    event BackupPriceFeedSet(address backupFeed);
    event EmergencyWithdraw(uint256 amount);
    event GoldReserveAudited(uint256 reserves, address auditor);
    event TokensPurchased(address indexed buyer, uint256 ethAmount, uint256 tokenAmount, uint256 tokenPrice);
    event TokensSold(address indexed seller, uint256 tokenAmount, uint256 ethAmount, uint256 tokenPrice);
    event PurchaseSettingsUpdated(bool enabled, uint256 markup);
    event SellSettingsUpdated(bool enabled, uint256 discount);
    event ETHWithdrawn(address indexed to, uint256 amount);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event LiquidityAdded(address indexed provider, uint256 amount);
    event InsufficientLiquidity(uint256 required, uint256 available);
    event ManualPriceSet(uint256 price, uint256 timestamp);
    event ManualPriceDisabled();
    event PriceFeedSwitched(bool useManual);

    // Modifiers
    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner");
        _;
    }
    
    modifier whenNotPaused() {
        require(!paused, "Contract is paused");
        _;
    }
    
    modifier validAddress(address addr) {
        require(addr != address(0), "Invalid address");
        _;
    }

    modifier whenPurchaseEnabled() {
        require(purchaseEnabled, "Token purchases are disabled");
        _;
    }

    modifier whenSellEnabled() {
        require(sellEnabled, "Token selling is disabled");
        _;
    }

    // Constructor
    constructor(address _goldPriceFeed, address _backupPriceFeed) {
        owner = msg.sender;
        goldPriceFeed = AggregatorV3Interface(_goldPriceFeed);
        backupPriceFeed = AggregatorV3Interface(_backupPriceFeed);
        lastMintResetTime = block.timestamp;
        lastPurchaseResetTime = block.timestamp;
        lastSellResetTime = block.timestamp;
        
        // Initial Supply - 20 Billion tokens
        uint256 initialSupply = 20 * 1000000000 * 10**18; // 20B tokens

        _totalSupply = initialSupply;
        _balances[owner] = _totalSupply;
        emit Transfer(address(0), owner, _totalSupply);
    }

    // ============= ERC-20 Core Functions =============
    
    /**
     * @dev Returns the name of the token.
     */
    function name() public view override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() public view override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() public view override returns (uint8) {
        return _decimals;
    }

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     * Returns a boolean value indicating whether the operation succeeded.
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) public override whenNotPaused returns (bool) {
        _transfer(msg.sender, to, amount);
        return true;
    }

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}.
     */
    function allowance(address tokenOwner, address spender) public view override returns (uint256) {
        return _allowances[tokenOwner][spender];
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     * Returns a boolean value indicating whether the operation succeeded.
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) public override whenNotPaused returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's allowance.
     * Returns a boolean value indicating whether the operation succeeded.
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) public override whenNotPaused returns (bool) {
        uint256 currentAllowance = _allowances[from][msg.sender];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        
        _transfer(from, to, amount);
        
        // Update allowance if not unlimited
        if (currentAllowance != type(uint256).max) {
            _approve(from, msg.sender, currentAllowance - amount);
        }
        
        return true;
    }

    // ============= Additional ERC-20 Functions =============

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     */
    function increaseAllowance(address spender, uint256 addedValue) public whenNotPaused returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public whenNotPaused returns (bool) {
        uint256 currentAllowance = _allowances[msg.sender][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        _approve(msg.sender, spender, currentAllowance - subtractedValue);
        return true;
    }

    // ============= Internal Functions =============

    /**
     * @dev Moves tokens from one account to another.
     */
    function _transfer(address from, address to, uint256 amount) internal validAddress(to) {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        
        uint256 senderBalance = _balances[from];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        
        _balances[from] = senderBalance - amount;
        _balances[to] += amount;
        
        emit Transfer(from, to, amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     */
    function _approve(address tokenOwner, address spender, uint256 amount) internal {
        require(tokenOwner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[tokenOwner][spender] = amount;
        emit Approval(tokenOwner, spender, amount);
    }

    // ============= Burn Functions =============

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the total supply.
     */
    function burn(uint256 amount) public whenNotPaused {
        require(_balances[msg.sender] >= amount, "ERC20: burn amount exceeds balance");
        
        _balances[msg.sender] -= amount;
        _totalSupply -= amount;
        
        emit Burn(msg.sender, amount);
        emit Transfer(msg.sender, address(0), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's allowance.
     */
    function burnFrom(address account, uint256 amount) public whenNotPaused {
        uint256 currentAllowance = _allowances[account][msg.sender];
        require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
        
        _approve(account, msg.sender, currentAllowance - amount);
        
        require(_balances[account] >= amount, "ERC20: burn amount exceeds balance");
        _balances[account] -= amount;
        _totalSupply -= amount;
        
        emit Burn(account, amount);
        emit Transfer(account, address(0), amount);
    }

    // ============= Oracle Functions =============
    
    function getLatestGoldPrice() public view returns (uint256) {
        // Check if manual price is enabled and valid
        if (manualPriceEnabled && manualGoldPrice > 0) {
            // Check if manual price is not too old (24 hours)
            require(block.timestamp - manualPriceTimestamp <= 86400, "Manual price too old");
            return manualGoldPrice;
        }
        // Otherwise use Chainlink oracle
        return _getValidatedPrice(goldPriceFeed);
    }
    
    function _getValidatedPrice(AggregatorV3Interface priceFeed) internal view returns (uint256) {
        (, int price, , uint256 timeStamp, ) = priceFeed.latestRoundData();
        
        require(timeStamp > 0, "Round not complete");
        require(block.timestamp - timeStamp <= PRICE_STALENESS_THRESHOLD, "Price data too old");
        require(price > 0, "Invalid price");
        
        uint256 uPrice = uint256(price);
        require(uPrice >= MIN_GOLD_PRICE && uPrice <= MAX_GOLD_PRICE, "Price out of bounds");
        
        return uPrice;
    }
    
    function getGoldPriceWithFallback() public view returns (uint256) {
        // First check manual price if enabled
        if (manualPriceEnabled && manualGoldPrice > 0) {
            if (block.timestamp - manualPriceTimestamp <= 86400) {
                return manualGoldPrice;
            }
        }
        
        // Then try primary oracle
        try this.getLatestGoldPrice() returns (uint256 price) {
            return price;
        } catch {
            // Fallback to backup price feed
            return _getValidatedPrice(backupPriceFeed);
        }
    }
    
    // ============= Manual Price Management =============
    
    /**
     * @dev Set gold price manually (owner only)
     * @param price The gold price in USD with 8 decimals (e.g., 2000_00000000 for $2000)
     */
    function setManualGoldPrice(uint256 price) public onlyOwner {
        require(price >= MIN_GOLD_PRICE && price <= MAX_GOLD_PRICE, "Price out of bounds");
        
        manualGoldPrice = price;
        manualPriceTimestamp = block.timestamp;
        manualPriceEnabled = true;
        
        emit ManualPriceSet(price, block.timestamp);
    }
    
    /**
     * @dev Disable manual price and revert to oracle pricing
     */
    function disableManualPrice() public onlyOwner {
        manualPriceEnabled = false;
        emit ManualPriceDisabled();
    }
    
    /**
     * @dev Toggle between manual and oracle pricing
     */
    function togglePriceMode(bool useManual) public onlyOwner {
        manualPriceEnabled = useManual;
        emit PriceFeedSwitched(useManual);
    }
    
    /**
     * @dev Get current price source information
     */
    function getPriceInfo() public view returns (
        bool isManualPrice,
        uint256 currentPrice,
        uint256 lastUpdateTime,
        string memory priceSource
    ) {
        isManualPrice = manualPriceEnabled && manualGoldPrice > 0 && 
                       (block.timestamp - manualPriceTimestamp <= 86400);
        
        if (isManualPrice) {
            currentPrice = manualGoldPrice;
            lastUpdateTime = manualPriceTimestamp;
            priceSource = "Manual";
        } else {
            try this.getLatestGoldPrice() returns (uint256 price) {
                currentPrice = price;
                (, , , uint256 timeStamp, ) = goldPriceFeed.latestRoundData();
                lastUpdateTime = timeStamp;
                priceSource = "Chainlink Oracle";
            } catch {
                currentPrice = _getValidatedPrice(backupPriceFeed);
                (, , , uint256 timeStamp, ) = backupPriceFeed.latestRoundData();
                lastUpdateTime = timeStamp;
                priceSource = "Backup Oracle";
            }
        }
    }
    
    /**
     * @dev Update manual price (same as set but updates existing)
     */
    function updateManualPrice(uint256 newPrice) public onlyOwner {
        require(manualPriceEnabled, "Manual price not enabled");
        require(newPrice >= MIN_GOLD_PRICE && newPrice <= MAX_GOLD_PRICE, "Price out of bounds");
        
        manualGoldPrice = newPrice;
        manualPriceTimestamp = block.timestamp;
        
        emit ManualPriceSet(newPrice, block.timestamp);
    }
    
    /**
     * @dev Compare manual price with oracle price
     */
    function comparePrices() public view returns (
        uint256 manualPrice,
        uint256 oraclePrice,
        int256 difference,
        uint256 percentDifference
    ) {
        manualPrice = manualGoldPrice;
        
        try goldPriceFeed.latestRoundData() returns (
            uint80,
            int256 price,
            uint256,
            uint256,
            uint80
        ) {
            oraclePrice = uint256(price);
        } catch {
            oraclePrice = 0;
        }
        
        if (oraclePrice > 0 && manualPrice > 0) {
            difference = int256(manualPrice) - int256(oraclePrice);
            
            // Calculate percentage difference (with 2 decimal precision)
            if (oraclePrice > manualPrice) {
                percentDifference = ((oraclePrice - manualPrice) * 10000) / oraclePrice;
            } else {
                percentDifference = ((manualPrice - oraclePrice) * 10000) / oraclePrice;
            }
        }
    }
    
    function getTokenPurchasePrice() public view returns (uint256) {
        uint256 goldPrice = getGoldPriceWithFallback();
        uint256 basePrice = (goldPrice + 50) / 100;
        return (basePrice * priceMarkup) / 100;
    }
    
    function getTokenSellPrice() public view returns (uint256) {
        uint256 goldPrice = getGoldPriceWithFallback();
        uint256 basePrice = (goldPrice + 50) / 100;
        return (basePrice * priceDiscount) / 100;
    }
    
    function getCurrentTokenValue() public view returns (uint256) {
        uint256 goldPrice = getGoldPriceWithFallback();
        return (goldPrice + 50) / 100;
    }

    // ============= Minting Functions =============
    
    function secureMint(address to, uint256 amount) public onlyOwner validAddress(to) whenNotPaused {
        require(amount > 0 && amount <= MAX_MINT_PER_TX, "Invalid mint amount");
        
        if (block.timestamp - lastMintResetTime >= 86400) {
            dailyMintAmount = 0;
            lastMintResetTime = block.timestamp;
        }
        
        require(dailyMintAmount + amount <= MAX_DAILY_MINT, "Daily mint limit exceeded");
        
        _balances[to] += amount;
        _totalSupply += amount;
        dailyMintAmount += amount;
        
        emit Mint(to, amount);
        emit Transfer(address(0), to, amount);
    }

    // ============= Purchase Functions =============
    
    function buyTokens() public payable whenNotPaused whenPurchaseEnabled {
        require(msg.value >= MIN_PURCHASE_ETH && msg.value <= MAX_PURCHASE_ETH, "Invalid ETH amount");
        
        if (block.timestamp - lastPurchaseResetTime >= 86400) {
            dailyPurchaseAmount = 0;
            lastPurchaseResetTime = block.timestamp;
        }
        
        uint256 tokenPrice = getTokenPurchasePrice();
        require(tokenPrice > 0, "Invalid token price");
        
        uint256 tokensAmount = (msg.value * 10**PRICE_DECIMALS) / tokenPrice;
        
        require(tokensAmount > 0, "Token amount too small");
        require(tokensAmount <= MAX_PURCHASE_PER_TX, "Exceeds max purchase per transaction");
        require(dailyPurchaseAmount + tokensAmount <= MAX_DAILY_PURCHASE, "Exceeds daily purchase limit");
        
        dailyPurchaseAmount += tokensAmount;
        
        _balances[msg.sender] += tokensAmount;
        _totalSupply += tokensAmount;
        
        emit TokensPurchased(msg.sender, msg.value, tokensAmount, tokenPrice);
        emit Transfer(address(0), msg.sender, tokensAmount);
    }

    // ============= Sell Functions =============
    
    /**
     * @dev Sell tokens back to the contract for ETH
     * @param tokenAmount The amount of tokens to sell
     */
    function sellTokens(uint256 tokenAmount) public whenNotPaused whenSellEnabled {
        require(tokenAmount >= MIN_SELL_TOKENS, "Below minimum sell amount");
        require(tokenAmount <= MAX_SELL_PER_TX, "Exceeds max sell per transaction");
        require(_balances[msg.sender] >= tokenAmount, "Insufficient token balance");
        
        // Reset daily counter if needed
        if (block.timestamp - lastSellResetTime >= 86400) {
            dailySellAmount = 0;
            lastSellResetTime = block.timestamp;
        }
        
        require(dailySellAmount + tokenAmount <= MAX_DAILY_SELL, "Exceeds daily sell limit");
        
        // Calculate ETH amount to send
        uint256 tokenPrice = getTokenSellPrice();
        require(tokenPrice > 0, "Invalid token price");
        
        uint256 ethAmount = (tokenAmount * tokenPrice) / 10**PRICE_DECIMALS;
        require(ethAmount > 0, "ETH amount too small");
        
        // Check contract has enough ETH
        uint256 contractBalance = address(this).balance;
        require(contractBalance >= ethAmount + MIN_CONTRACT_BALANCE, "Insufficient contract liquidity");
        
        // Update daily sell tracking
        dailySellAmount += tokenAmount;
        
        // Burn the tokens from seller
        _balances[msg.sender] -= tokenAmount;
        _totalSupply -= tokenAmount;
        
        // Send ETH to seller
        (bool success, ) = payable(msg.sender).call{value: ethAmount}("");
        require(success, "ETH transfer failed");
        
        emit TokensSold(msg.sender, tokenAmount, ethAmount, tokenPrice);
        emit Transfer(msg.sender, address(0), tokenAmount);
    }
    
    /**
     * @dev Calculate how much ETH would be received for selling tokens
     * @param tokenAmount The amount of tokens to calculate for
     */
    function calculateSellReturn(uint256 tokenAmount) public view returns (uint256) {
        uint256 tokenPrice = getTokenSellPrice();
        return (tokenAmount * tokenPrice) / 10**PRICE_DECIMALS;
    }
    
    /**
     * @dev Calculate how many tokens would be received for a given ETH amount
     * @param ethAmount The amount of ETH to calculate for
     */
    function calculatePurchaseReturn(uint256 ethAmount) public view returns (uint256) {
        uint256 tokenPrice = getTokenPurchasePrice();
        return (ethAmount * 10**PRICE_DECIMALS) / tokenPrice;
    }
    
    /**
     * @dev Check if the contract has enough liquidity for a sell
     * @param tokenAmount The amount of tokens to check
     */
    function canSellTokens(uint256 tokenAmount) public view returns (bool) {
        if (!sellEnabled || paused) return false;
        if (tokenAmount < MIN_SELL_TOKENS || tokenAmount > MAX_SELL_PER_TX) return false;
        
        uint256 ethAmount = calculateSellReturn(tokenAmount);
        uint256 contractBalance = address(this).balance;
        
        return contractBalance >= ethAmount + MIN_CONTRACT_BALANCE;
    }
    
    /**
     * @dev Add liquidity to the contract for selling operations
     */
    function addLiquidity() public payable onlyOwner {
        require(msg.value > 0, "Must send ETH");
        emit LiquidityAdded(msg.sender, msg.value);
    }

    // ============= Admin Functions =============
    
    function pause() public onlyOwner {
        paused = true;
        emit Paused();
    }
    
    function unpause() public onlyOwner {
        paused = false;
        emit Unpaused();
    }
    
    function emergencyWithdraw() public onlyOwner {
        uint256 balance = address(this).balance;
        payable(owner).transfer(balance);
        emit EmergencyWithdraw(balance);
    }
    
    function withdrawETH(uint256 amount) public onlyOwner {
        require(amount <= address(this).balance, "Insufficient contract balance");
        payable(owner).transfer(amount);
        emit ETHWithdrawn(owner, amount);
    }
    
    function withdrawAllETH() public onlyOwner {
        uint256 balance = address(this).balance;
        require(balance > 0, "No ETH to withdraw");
        payable(owner).transfer(balance);
        emit ETHWithdrawn(owner, balance);
    }
    
    function getETHBalance() public view returns (uint256) {
        return address(this).balance;
    }

    function setPurchaseEnabled(bool _enabled) public onlyOwner {
        purchaseEnabled = _enabled;
        emit PurchaseSettingsUpdated(_enabled, priceMarkup);
    }
    
    function setSellEnabled(bool _enabled) public onlyOwner {
        sellEnabled = _enabled;
        emit SellSettingsUpdated(_enabled, priceDiscount);
    }
    
    function setPriceMarkup(uint256 _markup) public onlyOwner {
        require(_markup >= 100 && _markup <= 200, "Markup must be between 100-200% (100-200)");
        priceMarkup = _markup;
        emit PurchaseSettingsUpdated(purchaseEnabled, _markup);
    }
    
    function setPriceDiscount(uint256 _discount) public onlyOwner {
        require(_discount >= 50 && _discount <= 100, "Discount must be between 50-100% (50-100)");
        priceDiscount = _discount;
        emit SellSettingsUpdated(sellEnabled, _discount);
    }
    
    /**
     * @dev Get current liquidity information
     */
    function getLiquidityInfo() public view returns (
        uint256 contractBalance,
        uint256 minBalance,
        bool canAcceptSells,
        uint256 maxSellableTokens
    ) {
        contractBalance = address(this).balance;
        minBalance = MIN_CONTRACT_BALANCE;
        canAcceptSells = contractBalance > MIN_CONTRACT_BALANCE;
        
        if (canAcceptSells) {
            uint256 availableETH = contractBalance - MIN_CONTRACT_BALANCE;
            uint256 tokenPrice = getTokenSellPrice();
            maxSellableTokens = (availableETH * 10**PRICE_DECIMALS) / tokenPrice;
        } else {
            maxSellableTokens = 0;
        }
    }
    
    function auditGoldReserves(uint256 auditedAmount) public onlyOwner {
        _goldReserves = auditedAmount;
        emit GoldReserveAudited(auditedAmount, msg.sender);
    }
    
    function setBackupPriceFeed(address newBackupFeed) public onlyOwner validAddress(newBackupFeed) {
        backupPriceFeed = AggregatorV3Interface(newBackupFeed);
        emit BackupPriceFeedSet(newBackupFeed);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public onlyOwner validAddress(newOwner) {
        address oldOwner = owner;
        owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
    /**
     * Limitation of Liability
     * The Developers, Creators, and Asset Managers of this Token shall not be held liable for any 
     * losses, damages, or claims arising out of or in connection with: (i) natural disasters or acts 
     * of God; (ii) market fluctuations, volatility, or defects in the open market; (iii) failures, 
     * defects, or technical errors in the Ethereum main network or any other blockchain infrastructure; 
     * or (iv) inaccuracies, delays, or alterations in the real-time price and/or value of gold or other 
     * assets backing the Token. By acquiring, holding, or transacting with this Token, the user expressly 
     * assumes all risks and agrees to release and hold harmless the Developers, Creators, and Asset Managers 
     * from any liability related to the foregoing. This message is placed on everything for transparency.
     */

    /**
     * @dev Leaves the contract without owner. Renouncing ownership will leave the contract
     * without an owner, thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        address oldOwner = owner;
        owner = address(0);
        emit OwnershipTransferred(oldOwner, address(0));
    }

    // ============= View Functions =============
    
    function goldReserves() public view returns (uint256) {
        return _goldReserves;
    }

    // Fallback function to receive ETH
    receive() external payable {}
}

Tags:
ERC20, Multisig, Mintable, Burnable, Pausable, Multi-Signature, Oracle|addr:0x986d434ed3e131a6f694027c35da8469840f9a49|verified:true|block:23467869|tx:0x03cb209aaded99e7dec94e9da788c6f0c37fa52ad49f6290bbba236e29b30545|first_check:1759142683

Submitted on: 2025-09-29 12:44:44

Comments

Log in to comment.

No comments yet.