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 {}
}
Submitted on: 2025-10-03 14:45:42
Comments
Log in to comment.
No comments yet.