Synthetic Bitcoin (sBTC)

Description:

ERC20 token contract with Oracle capabilities. Standard implementation for fungible tokens on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

/**
 * @title sBTC BEP20 Token pegged to BTC with Oracle Hooks
 * @notice BEP20 token with 8 decimals, no premint, commission+discount logic,
 * enforced min buy/redeem rules, hardcoded BTC addresses, owner-controlled rates,
 * and rescue functions for stuck tokens/BNB.
 */

interface IBEP20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IBEP20External {
    function transfer(address to, uint256 value) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

contract sBTC is IBEP20 {
    string public constant name = "Synthetic Bitcoin";
    string public constant symbol = "sBTC";
    uint8 public constant decimals = 8;

    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;

    address public owner;
    address public commissionWallet;

    uint256 public commissionRate; // basis points (100 = 1%)
    uint256 public discountRate;   // basis points (100 = 1%)

    uint256 public constant MIN_PURCHASE = 200 * 10**8; // 200 sBTC
    uint256 public constant MIN_REDEEM   = 200 * 10**8;
    uint256 public constant BTC_REQUIRED = 200 * 10**8; // indicator only

    /// @notice Hardcoded 6 backing BTC addresses
    string[6] public backingBTCAddresses = [
        "1N7jWmv63mkMdsYzbNUVHbEYDQfcq1u8Yp",
        "38UmuUqPCrFmQo4khkomQwZ4VbY2nZMJ67",
        "39eYrpgAgDhp4tTjrSb1ppZ5kdAc1ikBYw",
        "1NhJGUJu8rrTwPS4vopsdTqqcK4nAwdLwJ",
        "3FuhQLprN9s9MR3bZzR5da7mw75fuahsaU",
        "1Ki3WTEEqTLPNsN5cGTsMkL2sJ4m5mdCXT"
    ];

    /// @dev emitted for burn and redeem, picked up by off-chain oracle
    event BurnAndRedeem(address indexed user, uint256 sbtcAmount, string btcAddress, uint256 btcAmount);

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

    constructor(
        address _commissionWallet,
        uint256 _commissionRate,
        uint256 _discountRate
    ) {
        require(_commissionWallet != address(0), "Invalid commission wallet");
        owner = msg.sender;
        commissionWallet = _commissionWallet;
        commissionRate = _commissionRate;
        discountRate = _discountRate;
    }

    // ----------------------------
    // BEP20 Standard
    // ----------------------------

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

    function balanceOf(address account) external view override returns (uint256) {
        return _balances[account];
    }

    function transfer(address to, uint256 value) external override returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function allowance(address owner_, address spender) external view override returns (uint256) {
        return _allowances[owner_][spender];
    }

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

    function transferFrom(address from, address to, uint256 value) external override returns (bool) {
        uint256 allowed = _allowances[from][msg.sender];
        require(allowed >= value, "BEP20: allowance exceeded");
        _allowances[from][msg.sender] = allowed - value;
        _transfer(from, to, value);
        return true;
    }

    // ----------------------------
    // Core Mint / Burn
    // ----------------------------

    function _mint(address account, uint256 value) internal {
        _totalSupply += value;
        _balances[account] += value;
        emit Transfer(address(0), account, value);
    }

    function _burn(address account, uint256 value) internal {
        require(_balances[account] >= value, "BEP20: burn exceeds balance");
        _balances[account] -= value;
        _totalSupply -= value;
        emit Transfer(account, address(0), value);
    }

    function _transfer(address from, address to, uint256 value) internal {
        require(_balances[from] >= value, "BEP20: transfer exceeds balance");
        _balances[from] -= value;
        _balances[to] += value;
        emit Transfer(from, to, value);
    }

    // ----------------------------
    // Oracle Mint Functions
    // ----------------------------

    /// @notice Mint sBTC when oracle confirms official USDT deposit
    function mintOnDeposit(address buyer, uint256 amount) external onlyOwner {
        require(amount >= MIN_PURCHASE, "Minimum 200 sBTC required");
        _applyMint(buyer, amount);
    }

    /// @notice Mint sBTC when oracle confirms BTC deposit
    function mintOnBTC(address buyer, uint256 amount) external onlyOwner {
        require(amount >= MIN_PURCHASE, "Minimum 200 sBTC required");
        _applyMint(buyer, amount);
    }

    function _applyMint(address buyer, uint256 amount) internal {
        uint256 commission = (amount * commissionRate) / 10000;
        uint256 afterCommission = amount - commission;

        uint256 discount = (afterCommission * discountRate) / 10000;
        uint256 finalAmount = afterCommission + discount;

        if (commission > 0) {
            _mint(commissionWallet, commission);
        }
        _mint(buyer, finalAmount);
    }

    // ----------------------------
    // Burn and Redeem
    // ----------------------------

    function burnAndRedeem(uint256 amount, string memory btcAddress) external {
        require(amount >= MIN_REDEEM, "Minimum redeem is 200 sBTC");
        _burn(msg.sender, amount);
        emit BurnAndRedeem(msg.sender, amount, btcAddress, BTC_REQUIRED);
    }

    // ----------------------------
    // Owner Controls
    // ----------------------------

    function setCommissionWallet(address _wallet) external onlyOwner {
        commissionWallet = _wallet;
    }

    function setCommissionRate(uint256 _rate) external onlyOwner {
        require(_rate <= 1000, "Max 10%");
        commissionRate = _rate;
    }

    function setDiscountRate(uint256 _rate) external onlyOwner {
        require(_rate <= 1000, "Max 10%");
        discountRate = _rate;
    }

    // ----------------------------
    // Rescue Functions
    // ----------------------------

    /// @notice Rescue any BEP20 tokens mistakenly sent to this contract
    function rescueTokens(address token, address to) external onlyOwner {
        require(to != address(0), "Invalid address");
        uint256 balance = IBEP20External(token).balanceOf(address(this));
        require(balance > 0, "No balance");
        IBEP20External(token).transfer(to, balance);
    }

    /// @notice Rescue any BNB (native token) mistakenly sent to this contract
    function rescueBNB(address payable to) external onlyOwner {
        require(to != address(0), "Invalid address");
        uint256 balance = address(this).balance;
        require(balance > 0, "No BNB balance");
        to.transfer(balance);
    }

    // ----------------------------
    // Utility
    // ----------------------------

    function getBackingBTCAddresses() external view returns (string[6] memory) {
        return backingBTCAddresses;
    }

    // Accept BNB transfers (so rescue works if BNB sent by mistake)
    receive() external payable {}
}

Tags:
ERC20, Token, Oracle|addr:0x64be908d7097c3d292f8c99a83171726c254c3a9|verified:true|block:23497038|tx:0xac1680e1d66eced5852b6863aef34eacb53f1346a179cd736054db96d0e4db94|first_check:1759495541

Submitted on: 2025-10-03 14:45:42

Comments

Log in to comment.

No comments yet.