S Price: $0.518058 (+2.13%)

Contract Diff Checker

Contract Name:
StakingWithOptionalReferral

Contract Source Code:

File 1 of 1 : StakingWithOptionalReferral

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

/// @title StakingWithOptionalReferral - A staking contract for SANIC tokens with optional referrals and compounding rewards.
/// @dev This contract includes the IERC20 interface inline to avoid external imports.

interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, 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 sender, address recipient, 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);
}

contract StakingWithOptionalReferral {
    IERC20 public sanicToken; // Token to be staked
    address public feeRecipient; // Address to receive fees
    address public owner; // Contract owner

    uint256 public dailyRewardRate = 8; // 8% daily rewards
    uint256 public depositFee = 5; // 5% deposit fee
    uint256 public referralFee = 12; // 12% referral bonus if a referrer is provided

    struct User {
        uint256 depositedAmount;
        uint256 lastClaimTime;
    }

    mapping(address => User) public users;
    mapping(address => address) public referrers; // Tracks referrers for users

    event Deposit(
        address indexed user,
        uint256 amount,
        uint256 netAmount,
        address indexed referrer
    );
    event ClaimRewards(address indexed user, uint256 reward, uint256 fee);
    event Compound(address indexed user, uint256 compoundedAmount);
    event FeePaid(address indexed user, uint256 fee);
    event ReferralBonusPaid(address indexed referrer, uint256 bonus);
    event TokenUpdated(address indexed oldToken, address indexed newToken);
    event FeeRecipientUpdated(address indexed oldRecipient, address indexed newRecipient);

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

    constructor() {
        sanicToken = IERC20(0x18b7566936e19FdFff08A1e20c301bc401985666); // Hardcoded SANIC token address
        feeRecipient = 0x18b7566936e19FdFff08A1e20c301bc401985666; // Hardcoded fee recipient address
        owner = msg.sender;
    }

    function deposit(uint256 _amount, address _referrer) external {
        require(_amount > 0, "Deposit amount must be greater than zero");

        // Check allowance
        uint256 allowance = sanicToken.allowance(msg.sender, address(this));
        require(allowance >= _amount, "Token allowance too low. Approve the contract first.");

        // Check sender's balance
        uint256 balance = sanicToken.balanceOf(msg.sender);
        require(balance >= _amount, "Insufficient token balance for deposit.");

        // Transfer tokens from sender to contract
        bool success = sanicToken.transferFrom(msg.sender, address(this), _amount);
        require(success, "Token transfer failed");

        // Calculate deposit fee
        uint256 fee = (_amount * depositFee) / 100;
        uint256 netAmount = _amount - fee;

        // Transfer fee to feeRecipient
        success = sanicToken.transfer(feeRecipient, fee);
        require(success, "Fee transfer failed");

        // Handle optional referral bonus
        if (_referrer != address(0) && _referrer != msg.sender) {
            uint256 referralBonus = (_amount * referralFee) / 100;
            success = sanicToken.transfer(_referrer, referralBonus);
            require(success, "Referral bonus transfer failed");
            referrers[msg.sender] = _referrer;

            emit ReferralBonusPaid(_referrer, referralBonus);
        }

        // Update user's deposited amount and last claim time
        User storage user = users[msg.sender];
        user.depositedAmount += netAmount;
        user.lastClaimTime = block.timestamp;

        emit Deposit(msg.sender, _amount, netAmount, _referrer);
        emit FeePaid(msg.sender, fee);
    }

    function claimRewards() external {
        User storage user = users[msg.sender];
        require(user.depositedAmount > 0, "No deposits found");

        uint256 rewards = calculateRewards(msg.sender);
        require(rewards > 0, "No rewards available");

        // Calculate claim fee
        uint256 fee = (rewards * depositFee) / 100; // Claim rewards fee
        uint256 netRewards = rewards - fee;

        // Update user's last claim time
        user.lastClaimTime = block.timestamp;

        // Transfer net rewards to user
        bool success = sanicToken.transfer(msg.sender, netRewards);
        require(success, "Reward transfer failed");

        // Transfer fee to feeRecipient
        success = sanicToken.transfer(feeRecipient, fee);
        require(success, "Fee transfer failed");

        emit ClaimRewards(msg.sender, netRewards, fee);
    }

    function compound() external {
        User storage user = users[msg.sender];
        require(user.depositedAmount > 0, "No deposits found");

        uint256 rewards = calculateRewards(msg.sender);
        require(rewards > 0, "No rewards available");

        // Update user's last claim time
        user.lastClaimTime = block.timestamp;

        // Add rewards to deposited amount (compounding)
        user.depositedAmount += rewards;

        emit Compound(msg.sender, rewards);
    }

    function calculateRewards(address _user) public view returns (uint256) {
        User memory user = users[_user];
        uint256 elapsedTime = block.timestamp - user.lastClaimTime;
        uint256 dailyRewards = (user.depositedAmount * dailyRewardRate) / 100;
        return (dailyRewards * elapsedTime) / 1 days;
    }

    function updateToken(address _newToken) external onlyOwner {
        require(_newToken != address(0), "Invalid token address");
        address oldToken = address(sanicToken);
        sanicToken = IERC20(_newToken);
        emit TokenUpdated(oldToken, _newToken);
    }

    function updateFeeRecipient(address _newRecipient) external onlyOwner {
        require(_newRecipient != address(0), "Invalid fee recipient address");
        address oldRecipient = feeRecipient;
        feeRecipient = _newRecipient;
        emit FeeRecipientUpdated(oldRecipient, _newRecipient);
    }

    function getDepositedAmount(address _user) external view returns (uint256) {
        return users[_user].depositedAmount;
    }

    function getPendingRewards(address _user) external view returns (uint256) {
        return calculateRewards(_user);
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):