账户
0xe9...f160
0xe9...F160

0xe9...F160

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.6+commit.11564f7e
语言
Solidity
合同源代码
文件 1 的 1:Claim.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.6;

/**
 * @title Claim
 * @author gotbit
 */

interface IERC20 {
    function balanceOf(address who) external view returns (uint balance);
    function transfer(address to, uint value) external returns (bool trans1);
}

contract Ownable {
    address public owner;
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this function");
        _;
    }

    function transferOwnership(address newOwner_) external onlyOwner {
        require(
            newOwner_ != address(0),
            "You cant tranfer ownerships to address 0x0"
        );
        require(newOwner_ != owner, "You cant transfer ownerships to yourself");
        emit OwnershipTransferred(owner, newOwner_);
        owner = newOwner_;
    }
}

contract Claim is Ownable {
    struct Round {
        uint cliff;
        uint constReward;
        uint linearPeriod;
    }

    struct Allocation {
        uint seed;
        uint strategic;
        uint private_;
    }

    struct User {
        uint claimed;
        Allocation allocation;
        uint claimTimestamp;
    }

    uint public constant MONTH = 30 days;
    uint public constant MINUTE = 1 minutes;
    uint public constant CONST_PERIOD = 2 * 24 hours;
    uint public constant CONST_RELAX = MONTH;

    IERC20 public token;

    bool public isStarted;
    uint public startTimestamp;

    mapping(string => Round) rounds;
    mapping(address => User) public users;

    event Started(uint timestamp, address who);
    event Claimed(address indexed to, uint value);
    event SettedAllocation(address indexed to, uint seed, uint strategic, uint private_);


    constructor(address owner_, address token_) {
        owner = owner_;
        token = IERC20(token_);

        rounds["seed"] = Round(1, 10, 13);
        rounds["strategic"] = Round(0, 15, 9);
        rounds["private"] = Round(0, 20, 7);
    }

    function start() external onlyOwner returns (bool status) {
        require(!isStarted, "The claim has already begun");

        isStarted = true;
        startTimestamp = block.timestamp;

        emit Started(startTimestamp, msg.sender);

        return true;
    }

    function claim() external returns (bool status) {
        require(isStarted, "The claim has not started yet");

        uint value_ = calculateUnclaimed(msg.sender);

        require(value_ > 0, "You dont have DES to harvest");
        require(
            token.balanceOf(address(this)) >= value_,
            "Not enough tokens on contract"
        );

        users[msg.sender].claimed += value_;
        users[msg.sender].claimTimestamp = block.timestamp;

        require(token.transfer(msg.sender, value_), 'Transfer issues');

        emit Claimed(msg.sender, value_);
        return true;
    }

    function getAllocation(address user_) external view returns (uint sum) {
        return
            (users[user_].allocation.seed +
                users[user_].allocation.strategic +
                users[user_].allocation.private_) / 2;
    }

    function calculateUnclaimed(address user_)
        public
        view
        returns (uint unclaimed)
    {
        require(isStarted, "The claim has not started yet");

        uint resultSeed_ = calculateRound(
            "seed",
            users[user_].allocation.seed
        );
        uint resultStrategic_ = calculateRound(
            "strategic",
            users[user_].allocation.strategic
        );
        uint resultPrivate_ = calculateRound(
            "private",
            users[user_].allocation.private_
        );

        return
            (resultSeed_ + resultStrategic_ + resultPrivate_) /
            2 -
            users[user_].claimed;
    }

    function calculateRound(string memory roundName_, uint allocation_)
        internal
        view
        returns (uint unclaimedFromRound)
    {
        require(isStarted, "The claim has not started yet");

        Round memory round_ = rounds[roundName_];

        uint timePassed_ = block.timestamp - startTimestamp;
        uint bank_ = allocation_;

        if (timePassed_ < (round_.cliff * MONTH)) return 0;

        timePassed_ -= (round_.cliff * MONTH);
        uint constReward_ = (bank_ * round_.constReward) / 100;
        if (round_.cliff == 0) {
            if (timePassed_ < CONST_PERIOD / 2) return constReward_ / 2;
        }

        if (timePassed_ < CONST_RELAX) return constReward_;
        timePassed_ -= CONST_RELAX;

        uint minutesPassed_ = timePassed_ / MINUTE;
        uint leftInBank_ = bank_ - constReward_;
        return
            (leftInBank_ * MINUTE * minutesPassed_) /
            (MONTH * round_.linearPeriod) +
            constReward_;
    }

    function setAllocations(
        address[] memory whos_,
        uint[] memory seeds_,
        uint[] memory strategics_,
        uint[] memory privates_
    )
    public
    onlyOwner {
        uint len = whos_.length;
        require(seeds_.length == len, 'Different length');
        require(strategics_.length == len, 'Different length');
        require(privates_.length == len, 'Different length');

        for (uint i = 0; i < len; i++) {
            address who_ = whos_[i];

            if (users[who_].claimed == 0) {
                uint seed_ = seeds_[i];
                uint strategic_ = strategics_[i];
                uint private_ = privates_[i];
            
                users[who_] = User({
                    claimed: users[who_].claimed,
                    allocation: Allocation(seed_, strategic_, private_),
                    claimTimestamp: users[who_].claimTimestamp
                });
                emit SettedAllocation(who_, seed_, strategic_, private_);
            }
        }
    }
}
设置
{
  "compilationTarget": {
    "Claim.sol": "Claim"
  },
  "evmVersion": "berlin",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"token_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"seed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"strategic","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"private_","type":"uint256"}],"name":"SettedAllocation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"address","name":"who","type":"address"}],"name":"Started","type":"event"},{"inputs":[],"name":"CONST_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONST_RELAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINUTE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MONTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user_","type":"address"}],"name":"calculateUnclaimed","outputs":[{"internalType":"uint256","name":"unclaimed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[{"internalType":"bool","name":"status","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user_","type":"address"}],"name":"getAllocation","outputs":[{"internalType":"uint256","name":"sum","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"whos_","type":"address[]"},{"internalType":"uint256[]","name":"seeds_","type":"uint256[]"},{"internalType":"uint256[]","name":"strategics_","type":"uint256[]"},{"internalType":"uint256[]","name":"privates_","type":"uint256[]"}],"name":"setAllocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"start","outputs":[{"internalType":"bool","name":"status","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimestamp","outputs":[{"internalType":"uint256","name":"","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":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"uint256","name":"claimed","type":"uint256"},{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"strategic","type":"uint256"},{"internalType":"uint256","name":"private_","type":"uint256"}],"internalType":"struct Claim.Allocation","name":"allocation","type":"tuple"},{"internalType":"uint256","name":"claimTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"}]