BMBTokenStake

Description:

Smart contract deployed on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

/**
 *Submitted for verification at testnet.bscscan.com on 2025-09-08
*/

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

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _transferOwnership(_msgSender());
    }

    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

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

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

library TransferHelper {
    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }
}


interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
}

abstract contract ReentrancyGuard {
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }
    modifier nonReentrant() {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        _status = _ENTERED;

        _;

        _status = _NOT_ENTERED;
    }
}

contract BMBTokenStake is Ownable, ReentrancyGuard {
    address public addressBMB =  0x9447dd95f576fdF6ED8219ffF45BD1362430B787; 
    address public addressBMC =  0x0cA7244F798765De51A2b911f16EbCb7367362d1; 
    uint256 public stakeMinBMB = 100000;
    uint256 public stakeMinBMC = 100000;
    uint256 public unStakeTimeBMB = 4000000000;  //      ʼʱ  
    uint256 public unStakeTimeBMC = 4000000000;  //      ʼʱ  
    uint256 public releaseDaysBMB = 180;
    uint256 public releaseDaysBMC = 180;

    uint256 constant public secondsPerDay = 86400;  //     ʱ    100    ʾ100     һ 죬       86400  

    struct StakeInfo {
        uint256 id;
        address user;        //   Ѻ   û 
        address token;       //   Ѻ Ĵ   
        uint256 time;        //   Ѻʱ  
        uint256 stakeAmt;    //   Ѻ    
    }
    StakeInfo[] public stakeInfos;   //   Ѻ  Ϣ-ÿ    Ѻ

    mapping (address => mapping (address => uint256)) public userTokenStakeAmt;  //  û   Ѻij ҵ         û =>    =>    
    mapping (address => mapping (address => uint256)) public userTokenUnStakeAmt;  //  û    ij ҵ         û =>    =>    

    constructor() {
        stakeInfos.push(StakeInfo({id:1,user:address(0),token:address(0),time:0,stakeAmt:0}));
    }

    //   Ѻ  token    Լ  ַ  stakeAmt_         û             100000          Ȩ      Լ
    function stakeToken(address token_, uint256 stakeAmt_) external nonReentrant {
        require(_msgSender() == tx.origin, "Can not from contract.");
        require(addressBMB == token_ || addressBMC == token_, "Token Not Support.");
        if (addressBMB == token_) {
            require(block.timestamp < unStakeTimeBMB, "Stake Stopped.");
        
            require(stakeAmt_ >= stakeMinBMB, "Below the minimum investment amount.");

            if (unStakeTimeBMB == 4000000000) {
                unStakeTimeBMB = block.timestamp + releaseDaysBMB * secondsPerDay;
            }
        } else if (addressBMC == token_) {
            require(block.timestamp < unStakeTimeBMC, "Stake Stopped.");
        
            require(stakeAmt_ >= stakeMinBMC, "Below the minimum investment amount.");

            if (unStakeTimeBMC == 4000000000) {
                unStakeTimeBMC = block.timestamp + releaseDaysBMC * secondsPerDay;
            }
        }
        require(IERC20(token_).balanceOf(_msgSender()) >= stakeAmt_, "Balance Not Enough.");
        TransferHelper.safeTransferFrom(token_, _msgSender(), address(this), stakeAmt_);   


        StakeInfo memory di = StakeInfo({
            id: stakeInfos.length + 1,
            user: _msgSender(), 
            token: token_,
            time: block.timestamp, 
            stakeAmt: stakeAmt_
        });
        stakeInfos.push(di);

        userTokenStakeAmt[_msgSender()][token_] += stakeAmt_;
    }

    function redemption(address token_) external nonReentrant {
        require(addressBMB == token_ || addressBMC == token_, "Token Not Support.");
        if (addressBMB == token_) {
            require(block.timestamp >= unStakeTimeBMB, "UnStake Not Start.");
        } else if (addressBMC == token_) {
            require(block.timestamp >= unStakeTimeBMC, "UnStake Not Start.");
        }

        uint256 _returnAmt = userTokenStakeAmt[_msgSender()][token_] - userTokenUnStakeAmt[_msgSender()][token_];

        require(_returnAmt > 0, "No Token To Claim.");

        userTokenUnStakeAmt[_msgSender()][token_] += _returnAmt;
        TransferHelper.safeTransfer(token_, _msgSender(), _returnAmt);
    }

    //   ȡ û   Ѻ  Ϣ  _user   뵱ǰ û  ĵ ַ,token_     Һ Լ
    //    أ 
    // _minAmt    ǰ   ҵ   С  Ѻ    
    // _stakeAmt   ǰ û   ǰ     ܹ     Ѻ              صģ 
    // _unStakeAmt   ǰ û   ǰ     ܹ     ص     
    // _canUnStakeAmt   ǰ û   ǰ   ҿ     ص     

    //   ذ ť  _canUnStakeAmt > 0ʱ   Ե       ʱ      redemption    
    function getStakeInfos(address _user, address token_) public view returns(
        uint256 _minAmt, uint256 _stakeAmt, uint256 _unStakeAmt, uint256 _canUnStakeAmt) {
        
        if (addressBMB == token_) {
            _minAmt = stakeMinBMB;
            if (block.timestamp >= unStakeTimeBMB) {
                _canUnStakeAmt = userTokenStakeAmt[_user][token_] - userTokenUnStakeAmt[_user][token_];
            } else {
                _canUnStakeAmt = 0;
            }
            
        } else if (addressBMC == token_) {
            _minAmt = stakeMinBMC;

            if (block.timestamp >= unStakeTimeBMC) {
                _canUnStakeAmt = userTokenStakeAmt[_user][token_] - userTokenUnStakeAmt[_user][token_];
            } else {
                _canUnStakeAmt = 0;
            }
        }

        return (_minAmt, userTokenStakeAmt[_user][token_], userTokenUnStakeAmt[_user][token_], _canUnStakeAmt);  
    }

    function rescueToken(address tokenAddr_, uint256 amt_) external onlyOwner {
        TransferHelper.safeTransfer(tokenAddr_, owner(), amt_);
    }

    function rescueETH() external onlyOwner {
        uint256 balance = address(this).balance;
        payable(owner()).transfer(balance);
    }
}

Tags:
addr:0x4667468bde9fc417d4c6f266bfdff16a6038c01e|verified:true|block:23417466|tx:0x6db2262aa7056ad1e8f9589dcaeac58b9ac9b1e3aaef9bd2267be919f4fc44b6|first_check:1758537770

Submitted on: 2025-09-22 12:42:50

Comments

Log in to comment.

No comments yet.