Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft Abstract Staking logic #83

Merged
merged 13 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 152 additions & 10 deletions contracts/staking/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,185 @@
pragma solidity ^0.8.4;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import {ValueDistributor} from "./ValueDistributor.sol";

contract Staking is ValueDistributor {
address public tokenToDistribute;
uint256 public rate;
address private _sharesToken;
address private _rewardsToken;

function stake(uint256 amount_) public {
/**
* @dev The rate of rewards distribution per second.
*
* It determines the rate at which rewards are earned and distributed
* to stakers based on their shares.
*
* Note: Ensure that the `_rate` value is set correctly to match
* the decimal precision of the `_rewardsToken` to ensure accurate rewards distribution.
*/
uint256 private _rate;

uint256 private _stakingStartTime;

/**
* @dev Throws if the staking has not started yet.
*/
modifier stakingStarted() {
_checkStakingStarted();

Check warning on line 30 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L29-L30

Added lines #L29 - L30 were not covered by tests

Arvolear marked this conversation as resolved.
Show resolved Hide resolved
_;

Check warning on line 32 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L32

Added line #L32 was not covered by tests
}

/**
* @notice Initializes the contract setting the values provided by the deployer as shares token, rewards token, reward rate and staking start time.
* @param sharesToken_ The address of the shares token.
* @param rewardsToken_ The address of the rewards token.
* @param rate_ The reward rate.
* @param stakingStartTime_ The staking start time
*/
constructor(

Check warning on line 42 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L42

Added line #L42 was not covered by tests
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
address sharesToken_,
address rewardsToken_,
uint256 rate_,
uint256 stakingStartTime_
) {
require(sharesToken_ != address(0), "Staking: zero address cannot be the Shares Token");
require(rewardsToken_ != address(0), "Staking: zero address cannot be the Rewards Token");
require(rate_ > 0, "Rate has to be more than 0");

_sharesToken = sharesToken_;
_rewardsToken = rewardsToken_;
_setRate(rate_);
_setStakingStartTime(stakingStartTime_);

Check warning on line 55 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L52-L55

Added lines #L52 - L55 were not covered by tests
}

/**
* @notice Stakes the specified amount of tokens.
* @param amount_ The amount of tokens to stake.
*/
function stake(uint256 amount_) public stakingStarted {
_addShares(msg.sender, amount_);

Check warning on line 63 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L63

Added line #L63 was not covered by tests
}

function withdraw(uint256 amount_) public {
/**
* @notice Withdraws the specified amount of tokens.
* @param amount_ The amount of tokens to withdraw.
*/
function withdraw(uint256 amount_) public stakingStarted {
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
_removeShares(msg.sender, amount_);

Check warning on line 71 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L71

Added line #L71 was not covered by tests
}

function _changeDistributionToken(address newToken_) internal {
tokenToDistribute = newToken_;
/**
* @notice Claims the specified amount of rewards.
* @param amount_ The amount of rewards to claim.
*/
function claim(uint256 amount_) public stakingStarted {
uint256 owed = userDistribution(msg.sender).owedValue;

Check warning on line 79 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L79

Added line #L79 was not covered by tests
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
require(amount_ <= owed, "Insufficient amount");

distributeValue(msg.sender, amount_);

Check warning on line 82 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L82

Added line #L82 was not covered by tests
}

/**
* @notice Returns the shares token.
* @return The address of the shares token contract.
*/
function sharesToken() public view returns (address) {
return _sharesToken;

Check warning on line 90 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L89-L90

Added lines #L89 - L90 were not covered by tests
}

/**
* @notice Returns the rewards token.
* @return The address of the rewards token contract.
*/
function rewardsToken() public view returns (address) {
return _rewardsToken;

Check warning on line 98 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L97-L98

Added lines #L97 - L98 were not covered by tests
}

/**
* @notice Returns the staking start time.
* @return The timestamp when staking started.
*/
function stakingStartTime() public view returns (uint256) {
return _stakingStartTime;

Check warning on line 106 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L105-L106

Added lines #L105 - L106 were not covered by tests
}

/**
* @notice Returns the rate of rewards distribution.
* @return The rate of rewards distribution per second.
*/
function rate() public view returns (uint256) {
return _rate;

Check warning on line 114 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L113-L114

Added lines #L113 - L114 were not covered by tests
}

/**
* @notice Sets the staking start time.
* @param stakingStartTime_ The timestamp when staking will start.
*/
function _setStakingStartTime(uint256 stakingStartTime_) internal {
_stakingStartTime = stakingStartTime_;

Check warning on line 122 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L121-L122

Added lines #L121 - L122 were not covered by tests
}

/**
* @notice Sets the rate of rewards distribution per second.
* @param newRate_ The new rate of rewards distribution.
*/
function _setRate(uint256 newRate_) internal {
_update(address(0));

Check warning on line 130 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L129-L130

Added lines #L129 - L130 were not covered by tests

rate = newRate_;
_rate = newRate_;

Check warning on line 132 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L132

Added line #L132 was not covered by tests
}

/**
* @notice Hook function that is called after shares have been added to a user's distribution.
* @param user_ The address of the user.
* @param amount_ The amount of shares added.
*/
function _afterAddShares(address user_, uint256 amount_) internal virtual override {
IERC20(tokenToDistribute).transferFrom(user_, address(this), amount_); // FIXME USDT, decimals
SafeERC20.safeTransferFrom(IERC20(_sharesToken), user_, address(this), amount_);

Check warning on line 141 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L140-L141

Added lines #L140 - L141 were not covered by tests
}

/**
* @notice Hook function that is called after shares have been removed from a user's distribution.
*
* Note: All the rewards are claimed after the shares were removed.
*
* @param user_ The address of the user.
* @param amount_ The amount of shares removed.
*/
function _afterRemoveShares(address user_, uint256 amount_) internal virtual override {
IERC20(tokenToDistribute).transfer(user_, amount_); // FIXME USDT, decimals
SafeERC20.safeTransfer(IERC20(_sharesToken), user_, amount_);

Check warning on line 153 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L152-L153

Added lines #L152 - L153 were not covered by tests

distributeValue(msg.sender, getOwedValue(user_));

Check warning on line 155 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L155

Added line #L155 was not covered by tests
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @notice Hook function that is called after value has been distributed to a user.
* @param user_ The address of the user.
* @param amount_ The amount of value distributed.
*/
function _afterDistributeValue(address user_, uint256 amount_) internal virtual override {
SafeERC20.safeTransfer(IERC20(_rewardsToken), user_, amount_);

Check warning on line 164 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L163-L164

Added lines #L163 - L164 were not covered by tests
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @dev Throws if the staking has not started yet.
*/
function _checkStakingStarted() internal view {

Check warning on line 170 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L170

Added line #L170 was not covered by tests
require(block.timestamp >= _stakingStartTime, "Staking has not started yet");
}

/**
* @notice Gets the value to be distributed for a given time period.
* @param timeUpTo The end timestamp of the period.
* @param timeLastUpdate The start timestamp of the period.
* @return The value to be distributed for the period.
*/
function _getValueToDistribute(

Check warning on line 180 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L180

Added line #L180 was not covered by tests
uint256 timeUpTo,
uint256 timeLastUpdate
) internal view virtual override returns (uint256) {
return rate * (timeUpTo - timeLastUpdate);
return _rate * (timeUpTo - timeLastUpdate);

Check warning on line 184 in contracts/staking/Staking.sol

View check run for this annotation

Codecov / codecov/patch

contracts/staking/Staking.sol#L184

Added line #L184 was not covered by tests
}
}
Loading