Staking

Description:

Decentralized Finance (DeFi) protocol contract providing Staking functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

interface IVault {
    function deposit() external payable;
    function withdraw(uint256 amount, address to) external;
}

interface IReward {
    function addReward(address user, uint256 amount) external;
}

contract Staking {
    address public owner;

    IVault public vault;
    IReward public reward;

    uint256 public constant MAX_STAKES_PER_USER = 100;

    struct StakeInfo {
        uint256 amount;
        uint256 startTime;
        uint256 lockupPeriod;
        bool claimed;
    }

    mapping(address => StakeInfo[]) public stakes;
    mapping(uint256 => uint256) public lockupRewardPercents;

    // --- ReentrancyGuard 
    uint256 private _status;
    modifier nonReentrant() {
        require(_status != 2, "ReentrancyGuard: reentrant call");
        _status = 2;
        _;
        _status = 1;
    }

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

    constructor() {
        owner = msg.sender;

       
        vault = IVault(0x40b5aF46D2833Be7Ee22Ff139Ec3CAe9B04D08DC);
        reward = IReward(0x2795717F2D0e9325b79Fe1B7e22540A3e7dFA6E5);

    
        lockupRewardPercents[15 days] = 5;
        lockupRewardPercents[30 days] = 15;
        lockupRewardPercents[60 days] = 35;
        lockupRewardPercents[90 days] = 55;
        lockupRewardPercents[180 days] = 115;
        lockupRewardPercents[365 days] = 230;

        _status = 1;
    }

    function stake(uint256 _lockupPeriod) external payable nonReentrant {
        require(msg.value > 0, "Stake must be > 0");
        require(lockupRewardPercents[_lockupPeriod] > 0, "Invalid lockup period");
        require(stakes[msg.sender].length < MAX_STAKES_PER_USER, "Too many stakes");

        stakes[msg.sender].push(
            StakeInfo({
                amount: msg.value,
                startTime: block.timestamp,
                lockupPeriod: _lockupPeriod,
                claimed: false
            })
        );

        vault.deposit{value: msg.value}();
    }

    function claimReward(uint256 index) external nonReentrant {
        StakeInfo storage stakeData = stakes[msg.sender][index];
        require(!stakeData.claimed, "Already claimed");
        require(block.timestamp >= stakeData.startTime + stakeData.lockupPeriod, "Still locked");

        uint256 rewardAmount = calculateReward(stakeData.amount, stakeData.lockupPeriod);
        stakeData.claimed = true;

        reward.addReward(msg.sender, rewardAmount);
    }

    function unstake(uint256 index) external nonReentrant {
        StakeInfo storage stakeData = stakes[msg.sender][index];
        require(block.timestamp >= stakeData.startTime + stakeData.lockupPeriod, "Still locked");

        uint256 amount = stakeData.amount;

       
        uint256 lastIndex = stakes[msg.sender].length - 1;
        if (index != lastIndex) {
            stakes[msg.sender][index] = stakes[msg.sender][lastIndex];
        }
        stakes[msg.sender].pop();

        vault.withdraw(amount, msg.sender);
    }

    function calculateReward(uint256 amount, uint256 lockup) public view returns (uint256) {
        uint256 percent = lockupRewardPercents[lockup];
        return (amount * percent) / 100;
    }

    function getStakes(address user) external view returns (StakeInfo[] memory) {
        return stakes[user];
    }

    function setLockupRewardPercent(uint256 period, uint256 percent) external onlyOwner {
        lockupRewardPercents[period] = percent;
    }

    function setVault(address _vault) external onlyOwner {
        require(_vault != address(0), "Invalid address");
        vault = IVault(_vault);
    }

    function setReward(address _reward) external onlyOwner {
        require(_reward != address(0), "Invalid address");
        reward = IReward(_reward);
    }
}

Tags:
DeFi, Staking|addr:0xf26ed493e5bb8d363932851ca59b4054f45a472b|verified:true|block:23461096|tx:0x636ec21e45ef1c18b7c9c17998c0cb6193d2a4cb20ca87b16a095fd4558e683f|first_check:1759058029

Submitted on: 2025-09-28 13:13:49

Comments

Log in to comment.

No comments yet.