/**
*Submitted for verification at BscScan.com on 2022-06-14
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, “SafeMath: addition overflow”);
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, “SafeMath: subtraction overflow”);
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity’s `-` operator.
*
* Requirements:
* – Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a – b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity’s `*` operator.
*
* Requirements:
* – Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring ‘a’ not being zero, but the
// benefit is lost if ‘b’ is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, “SafeMath: multiplication overflow”);
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity’s `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* – The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, “SafeMath: division by zero”);
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity’s `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* – The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn’t hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity’s `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* – The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, “SafeMath: modulo by zero”);
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity’s `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* – The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), “Ownable: caller is not the owner”);
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(
newOwner != address(0),
“Ownable: new owner is the zero address”
);
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
interface IBEP20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function name() external view returns (string memory);
function getOwner() external view returns (address);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function allowance(address _owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(
address(this).balance >= amount,
“Address: insufficient balance”
);
(bool success, ) = recipient.call{value: amount}(“”);
require(
success,
“Address: unable to send value, recipient may have reverted”
);
}
function functionCall(address target, bytes memory data)
internal
returns (bytes memory)
{
return functionCall(target, data, “Address: low-level call failed”);
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return
functionCallWithValue(
target,
data,
value,
“Address: low-level call with value failed”
);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(
address(this).balance >= value,
“Address: insufficient balance for call”
);
require(isContract(target), “Address: call to non-contract”);
(bool success, bytes memory returndata) = target.call{value: value}(
data
);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data)
internal
view
returns (bytes memory)
{
return
functionStaticCall(
target,
data,
“Address: low-level static call failed”
);
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), “Address: static call to non-contract”);
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data)
internal
returns (bytes memory)
{
return
functionDelegateCall(
target,
data,
“Address: low-level delegate call failed”
);
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), “Address: delegate call to non-contract”);
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
library SafeBEP20 {
using Address for address;
function safeTransfer(
IBEP20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transfer.selector, to, value)
);
}
function safeTransferFrom(
IBEP20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IBEP20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IBEP20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// ‘safeIncreaseAllowance’ and ‘safeDecreaseAllowance’
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
“SafeBEP20: approve from non-zero to non-zero allowance”
);
_callOptionalReturn(
token,
abi.encodeWithSelector(token.approve.selector, spender, value)
);
}
function safeIncreaseAllowance(
IBEP20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
spender,
newAllowance
)
);
}
function safeDecreaseAllowance(
IBEP20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(
oldAllowance >= value,
“SafeBEP20: decreased allowance below zero”
);
uint256 newAllowance = oldAllowance – value;
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
spender,
newAllowance
)
);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IBEP20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity’s return data size checking mechanism, since
// we’re implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(
data,
“SafeBEP20: low-level call failed”
);
if (returndata.length > 0) {
// Return data is optional
require(
abi.decode(returndata, (bool)),
“SafeBEP20: BEP20 operation did not succeed”
);
}
}
}
contract Staking is Ownable {
using SafeBEP20 for IBEP20;
using SafeMath for uint256;
uint256 public minimumDepositeAmount;
uint256 public maximumDepositeAmount;
IBEP20 public stakedToken;
IBEP20 public rewardToken;
struct stack {
uint256 amount;
address userAddress;
uint256 depositeTime;
uint256 stackId;
bool isWithdrawal;
uint256 userAPY;
}
mapping(uint256 => stack) public Stack;
uint256 public APYS=200;
address[] public stakeholders;
bool hasStart = true;
uint256 public currentID = 0;
function startStacking() public onlyOwner {
require(hasStart == false, “Stacking Already Started”);
hasStart = true;
}
function pauseStacking() public onlyOwner {
require(hasStart == true, “Stacking Already Paused”);
hasStart = false;
}
function setDepositeAmount(uint256 minimumAmount, uint256 maximumAmount)
public onlyOwner
{
maximumDepositeAmount = maximumAmount;
minimumAmount = minimumAmount;
}
function setAPY(uint256 _APY) public onlyOwner {
APYS=_APY;
}
function isStakeholder(address _address)
public
view
returns (bool, uint256)
{
for (uint256 s = 0; s < stakeholders.length; s += 1) {
if (_address == stakeholders[s]) return (true, s);
}
return (false, 0);
}
function addStakeholder(address _stakeholder) internal {
(bool _isStakeholder, ) = isStakeholder(_stakeholder);
if (!_isStakeholder) stakeholders.push(_stakeholder);
}
function removeStakeholder(address _stakeholder) internal {
(bool _isStakeholder, uint256 s) = isStakeholder(_stakeholder);
if (_isStakeholder) {
stakeholders[s] = stakeholders[stakeholders.length – 1];
stakeholders.pop();
}
}
function userInfo(uint256 amount) internal {
Stack[currentID].amount = amount.mul(1e18);
Stack[currentID].userAddress = msg.sender;
Stack[currentID].userAPY = APYS;
Stack[currentID].depositeTime = block.timestamp;
Stack[currentID].stackId = currentID;
Stack[currentID].isWithdrawal = false;
addStakeholder(msg.sender);
currentID = currentID + 1;
}
function deposite(uint256 amount) public {
require(hasStart == true, “Stacking is not Start yet”);
require(
amount >= minimumDepositeAmount,
“Amount Must be Gratar than minimum Deposite Amount”
);
require(
amount <= maximumDepositeAmount,
“Amount Must be less than maximum Deposite Amount”
);
require(
stakedToken.allowance(msg.sender, address(this)) > amount.mul(1e18),
“please allow fund first”
);
stakedToken.safeTransferFrom(
msg.sender,
address(this),
amount.mul(1e18)
);
userInfo(amount);
}
function calclulateReward(uint256 id) public view returns (uint256) {
if(Stack[id].amount>0){
uint256 depositeTime = Stack[id].depositeTime;
uint256 currentTime = block.timestamp;
uint256 tps = ((Stack[id].userAPY).mul(1e18)).div(100 * 86400 * 365);
uint256 reward = (currentTime.sub(depositeTime)).mul(tps);
return (reward);
}else{
return uint256(0);
}
}
function withdrawl(uint256 amount) public onlyOwner {
require(
stakedToken.balanceOf(address(this)) >= amount.mul(1e18),
“Contract balance is low”
);
stakedToken.safeTransfer(msg.sender, amount.mul(1e18));
}
function withdrawRewardToken(uint256 amount) public onlyOwner {
require(
rewardToken.balanceOf(address(this)) >= amount.mul(1e18),
“Contract balance is low”
);
rewardToken.safeTransfer(msg.sender, amount.mul(1e18));
}
function claim(uint256 id) public {
require(hasStart == true, “Stacking is not Start yet”);
require(Stack[id].isWithdrawal == false, “Amount Already withdrawl”);
require(Stack[id].userAddress == msg.sender, “Only Stack owner can claim tokens “);
uint256 reward = calclulateReward(id);
uint256 totalAmount = (Stack[id].amount).mul(reward).div(1e18);
require(
rewardToken.balanceOf(address(this)) >= totalAmount,
“Insufficent Balance”
);
uint256 remainingAmount = 0;
if(block.timestamp-Stack[id].depositeTime <= 300){ // same block
remainingAmount = Stack[id].amount.mul(25).div(100);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime <= 3600){ // in one hour
remainingAmount = Stack[id].amount.mul(8).div(100);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime <= 86400){ // in 24 hour
remainingAmount = Stack[id].amount.mul(4).div(100);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime <= 3 days){ // in three days
remainingAmount = Stack[id].amount.mul(2).div(100);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime <= 7 days){ // in one week
remainingAmount = Stack[id].amount.mul(1).div(100);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime > 7 days && block.timestamp-Stack[id].depositeTime <= 14 days){ // into 1 week to 2 week
remainingAmount = Stack[id].amount.mul(5).div(1000);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime > 14 days && block.timestamp-Stack[id].depositeTime <= 28 days){ // into 2 week to 4 week
remainingAmount = Stack[id].amount.mul(4).div(1000);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime > 28 days && block.timestamp-Stack[id].depositeTime <= 42 days){ // into 4 week to 6 week
remainingAmount = Stack[id].amount.mul(3).div(1000);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime > 42 days && block.timestamp-Stack[id].depositeTime <= 56 days){ // into 6 week to 8 week
remainingAmount = Stack[id].amount.mul(2).div(1000);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime > 56 days && block.timestamp-Stack[id].depositeTime <= 70 days){ // into 8 week to 10 week
remainingAmount = Stack[id].amount.mul(2).div(1000);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime > 70 days && block.timestamp-Stack[id].depositeTime <= 84 days){ // into 10 week to 12 week
remainingAmount = Stack[id].amount.mul(5).div(10000);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}else if(block.timestamp-Stack[id].depositeTime > 84 days && block.timestamp-Stack[id].depositeTime <= 84 days){ // into 10 week to 12 week
remainingAmount = Stack[id].amount.mul(1).div(10000);
remainingAmount = Stack[id].amount.sub(remainingAmount);
}
Stack[id].isWithdrawal = true;
rewardToken.safeTransfer(Stack[id].userAddress, totalAmount);
stakedToken.safeTransfer(Stack[id].userAddress,remainingAmount);
}
constructor(IBEP20 _stakedToken,IBEP20 _rewardToken) {
minimumDepositeAmount = 100;
maximumDepositeAmount = 10000;
stakedToken = IBEP20(_stakedToken);
rewardToken = IBEP20(_rewardToken);
}
}