如何在构造函数中添加一个 uint T,它将成为我的智能合约中的一个时间常数?

How to add a uint T in constructor that will be a time constant inside my smart contract?

我需要一个时间常数来计算存款、取款和奖励子池的时间戳。这个称为 T 的时间常数将从合约部署开始,并且不会特定于一个 address/user。即奖励(R)被分为 3 个子池:R1 = 20% 在合约部署后 2T 后可用,R2 = 30% 在合约部署后 3T 后可用, R3= 50% 在合约部署后 4T 后可用。我需要这个变量以分钟为单位,比如发送方输入3 我希望每个时间戳之间的时间是3,比如存款在第一个T,取款在3T之后。如何分分钟设置? 这里是状态变量

uint256 public T;

这里是构造函数

constructor(address stakingToken, address rewardsToken, uint256 timeConstant) {
        s_stakingToken = IERC20(stakingToken);
        s_rewardsToken = IERC20(rewardsToken);
        initialTime = block.timestamp;
        T = timeConstant;
    }

我的完整代码

    error TransferFailed();
    error NeedsMoreThanZero();
    
    contract Staking is ReentrancyGuard {
        IERC20 public s_rewardsToken;
        IERC20 public s_stakingToken;
    
        // This is the reward token per seco

nd
    // Which will be multiplied by the tokens the user staked divided by the total
    // This ensures a steady reward rate of the platform
    // So the more users stake, the less for everyone who is staking.
    uint256 public constant REWARD_RATE = 100;
    uint256 public s_lastUpdateTime;
    uint256 public s_rewardPerTokenStored;
    //uint256 public constant T = 3;
    uint256 public initialTime;
    uint256 public T;

    mapping(address => uint256) public s_userRewardPerTokenPaid;
    mapping(address => uint256) public s_rewards;

    uint256 private s_totalSupply;
    mapping(address => uint256) public s_balances; // someones address => how much he staked

    event Staked(address indexed user, uint256 indexed amount);
    event WithdrewStake(address indexed user, uint256 indexed amount);
    event RewardsClaimed(address indexed user, uint256 indexed amount);

    constructor(address stakingToken, address rewardsToken, uint256 timeConstant) {
        s_stakingToken = IERC20(stakingToken);
        s_rewardsToken = IERC20(rewardsToken);
        initialTime = block.timestamp;
        T = timeConstant;
    }

    /**
     * @notice How much reward a token gets based on how long it's been in and during which "snapshots"
     */
    function rewardPerToken() public view returns (uint256) {
        if (s_totalSupply == 0) {
            return s_rewardPerTokenStored;
        }
        return
            s_rewardPerTokenStored +
            (((block.timestamp - s_lastUpdateTime) * REWARD_RATE * 1e18) / s_totalSupply);
    }

    /**
     * @notice How much reward a user has earned
     */
    function earned(address account) public view returns (uint256) {
        uint256 nowTime = block.timestamp-initialTime;
        require(nowTime > 2*T);
        if (nowTime > 2*T && nowTime <= 3*T) {
                return
            ((((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
                1e18) + s_rewards[account]) / 5 );
        } else if
            (nowTime > 3*T && nowTime <= 4*T) {
                return
            ((((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
                1e18) + s_rewards[account]) / 2 );
        } else {
            return
            (((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
                1e18) + s_rewards[account]);
        }
        
    }

    /**
     * @notice Deposit tokens into this contract
     * @param amount | How much to stake
     */
    function stake(uint256 amount)
        external
        updateReward(msg.sender)
        nonReentrant
        moreThanZero(amount)
    {
        //from T0 to T deposit is available
        uint256 nowTime = block.timestamp-initialTime; // time between deployment of contract and now.
        require(nowTime < T);
        s_totalSupply += amount; 
        // increasing how much they are staking for how much they staked each time.
        s_balances[msg.sender] += amount; 
        emit Staked(msg.sender, amount);
        // sending an amount of token from an address to this contract
        bool success = s_stakingToken.transferFrom(msg.sender, address(this), amount);  
        // if not successfully sent, return an error.
        // using the below code instead of "require(success, "Failed")" reduces gas fees, since it doesn't output a string.
        if (!success) {
            revert TransferFailed(); // revert resets everything done in a failed transaction.
        }
    }

    /**
     * @notice Withdraw tokens from this contract
     * @param amount | How much to withdraw
     */
    function withdraw(uint256 amount) external updateReward(msg.sender) nonReentrant {
        // from 2T the user can reward his tokens
        uint256 nowTime = block.timestamp-initialTime; // time between deployment of contract and now.
        require(nowTime > 2* T);
        s_totalSupply -= amount;
        s_balances[msg.sender] -= amount;
        emit WithdrewStake(msg.sender, amount);
        // transfer: send tokens from contract back to msg.sender.
        bool success = s_stakingToken.transfer(msg.sender, amount);
        if (!success) {
            revert TransferFailed(); // revert resets everything done in a failed transaction.
        }
    }

    /**
     * @notice User claims their tokens
     */
    function claimReward() external updateReward(msg.sender) nonReentrant {
        uint256 reward = s_rewards[msg.sender];
        s_rewards[msg.sender] = 0;
        emit RewardsClaimed(msg.sender, reward);
        bool success = s_rewardsToken.transfer(msg.sender, reward);
        if (!success) {
            revert TransferFailed(); // revert resets everything done in a failed transaction.
        }
    }

    /********************/
    /* Modifiers Functions */
    /********************/
    modifier updateReward(address account) {
        s_rewardPerTokenStored = rewardPerToken();
        s_lastUpdateTime = block.timestamp;
        s_rewards[account] = earned(account);
        s_userRewardPerTokenPaid[account] = s_rewardPerTokenStored;
        _;
    }

    modifier moreThanZero(uint256 amount) {
        if (amount == 0) {
            revert NeedsMoreThanZero();
        }
        _;
    }

    /********************/
    /* Getter Functions */
    /********************/
    // Ideally, we'd have getter functions for all our s_ variables we want exposed, and set them all to private.
    // But, for the purpose of this demo, we've left them public for simplicity.

    function getStaked(address account) public view returns (uint256) {
        return s_balances[account];
    }
}

首先维护一个映射,用于存储每个用户的时间。然后制作诸如 depositTimeSet 、 withdrawalTimeSet 之类的函数,用于为不同的用户存储不同的时间。存入时更新变量,取款时检查时间是否超过。

struct Users {
        uint dipositTime;
        uint withDrawTime;
        uint lastDepositTime;
}
mapping(address => Users ) users;

function depositeTimeSet(uint t) {
  users[msg.sender].dipositTime = t minutes;
  withdrawalTimeSet(t);
}
function withdrawalTimeSet(uint t) {
  users[msg.sender].withDrawTime = 3 * t minutes
}
function deposite() {
  transferFrom(msg.sender,address(this));
  depositeTimeSet(3); // considering sender send 3
  users[msg.sender].lastDepositTime = now;
}
function withdraw() {
  if(
     now > users[msg.sender].lastDepositTime + 
     users[msg.sender].withDrawTime,"too early for withdraw 
     request"
  )
  transferFrom(address(this),msg.sender);
}

您可以看到 THIS 一个可能会有帮助

您可以在 solidity 中看到 THIS 时间单位资源