// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.21;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract DudeStake is Ownable {
    using SafeMath for uint256;

    struct StakeInfo {
        uint256 amount;
        uint256 endAt;
        uint256 total;
        uint256 earned;
    }

    mapping(address => StakeInfo) public stakes;

    IERC20 public token;
    uint256 public arp = 55;
    uint256 public fee = 4;
    address public pool;
    uint256 public stakeTime = 7 days;
    uint256 public minimal = 1000 * 1e18;

    uint256 public holderShare = 4;
    address[] public holders;

    constructor(IERC20 token_) Ownable() {
        token = token_;
        pool = msg.sender;
    }

    function stake(uint256 amount) public {
        require(amount >= minimal, "too small");
        require(token.transferFrom(msg.sender, pool, amount), "can not transfer");
        StakeInfo storage info = stakes[msg.sender];
        info.amount = info.amount.add(amount);
        info.endAt = block.timestamp + stakeTime;
        info.total = info.total.add(amount);
    }

    function unStake() public {
        StakeInfo storage info = stakes[msg.sender];

        require(info.amount > 0, "can not un-stake");

        uint256 unStakeAmount;
        uint256 holderAmount;

        if (block.timestamp <= info.endAt) {
            uint256 feeAmount = info.amount.mul(fee).div(100);
            holderAmount = feeAmount.mul(holderShare).div(100);
            unStakeAmount = info.amount.sub(feeAmount);
        } else {
            uint256 reward = info.amount.mul(stakeTime).div(365 days).mul(arp).div(100);
            holderAmount = reward.mul(holderShare).div(100);
            unStakeAmount = info.amount.add(reward.sub(holderShare));
            info.earned = info.earned.add(reward.sub(holderShare));
        }

        require(token.transferFrom(pool, msg.sender, unStakeAmount), "can not transfer");
        require(token.transferFrom(pool, address(this), holderAmount), "can not transfer");

        info.amount = 0;
        info.endAt = 0;
    }

    function setHolders(address[] memory _holders) public onlyOwner {
        holders = _holders;
    }

    function airdrop() public onlyOwner {
        uint256 len = holders.length;
        uint256 holderAmount = token.balanceOf(address(this));
        require(len > 0 && holderAmount > 0, "airdrop");
        uint256 amount = holderAmount.div(len);
        for (uint256 i=1; i < len; i++) {
            require(token.transfer(holders[i], amount), "can not transfer");
            holderAmount = holderAmount.sub(amount);
        }
        token.transfer(holders[0], holderAmount);
    }
}
[{"inputs":[{"internalType":"contract IERC20","name":"token_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"arp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holderShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"holders","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_holders","type":"address[]"}],"name":"setHolders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakes","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"endAt","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"earned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unStake","outputs":[],"stateMutability":"nonpayable","type":"function"}]