-
-
Save barchef/bb45ae3124cee992c3117818e4ffe388 to your computer and use it in GitHub Desktop.
LockerStaking.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity 0.8.13; | |
pragma experimental ABIEncoderV2; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import "@openzeppelin/contracts/utils/math/SafeMath.sol"; | |
import "@openzeppelin/contracts/utils/Address.sol"; | |
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; | |
contract LockerStaking is ReentrancyGuard, Ownable { | |
using SafeMath for uint256; | |
using Address for address; | |
using SafeERC20 for IERC20; | |
IERC20 public lockerToken; | |
event Staked(address indexed from, uint256 amount); | |
event Unstaked(address indexed from, uint256 amount); | |
struct AccountInfo { | |
uint256 balance; | |
uint256 lastStakedTimestamp; | |
uint256 lastUnstakedTimestamp; | |
} | |
mapping(address => AccountInfo) public accountInfos; | |
uint256[] public burnFees = [1000, 700, 500, 200, 50]; | |
uint256[] public feeCycle = [3 days, 7 days, 14 days, 30 days]; | |
constructor(address _lockerToken) public { | |
lockerToken = IERC20(_lockerToken); | |
} | |
function stake(uint256 _amount) public nonReentrant { | |
require(_amount > 0, "Invalid amount"); | |
require(lockerToken.balanceOf(msg.sender) >= _amount, "Invalid balance"); | |
AccountInfo storage account = accountInfos[msg.sender]; | |
lockerToken.transferFrom(msg.sender, address(this), _amount); | |
account.balance = account.balance.add(_amount); | |
if (account.lastUnstakedTimestamp == 0) { | |
account.lastUnstakedTimestamp = block.timestamp; | |
} | |
account.lastStakedTimestamp = block.timestamp; | |
emit Staked(msg.sender, _amount); | |
} | |
function unstake(uint256 _amount) external nonReentrant { | |
AccountInfo storage account = accountInfos[msg.sender]; | |
require( | |
!address(msg.sender).isContract(), | |
"Please use your individual account" | |
); | |
require(account.balance > 0, "Nothing to unstake"); | |
require(_amount > 0, "Invalid amount"); | |
if (account.balance < _amount) { | |
_amount = account.balance; | |
} | |
account.balance = account.balance.sub(_amount); | |
uint256 burnAmount = _amount.mul(getBurnFee(msg.sender)).div(10000); | |
if (burnAmount > 0) { | |
_amount = _amount.sub(burnAmount); | |
lockerToken.transfer( | |
address(0x000000000000000000000000000000000000dEaD), | |
burnAmount | |
); | |
} | |
account.lastUnstakedTimestamp = block.timestamp; | |
if (account.balance == 0) { | |
account.lastStakedTimestamp = 0; | |
account.lastUnstakedTimestamp = 0; | |
} | |
lockerToken.transfer(msg.sender, _amount); | |
emit Unstaked(msg.sender, _amount); | |
} | |
function getBurnFee(address _staker) public view returns (uint256) { | |
AccountInfo memory account = accountInfos[_staker]; | |
for (uint256 i = 0; i < feeCycle.length; i++) { | |
if (block.timestamp < account.lastUnstakedTimestamp + feeCycle[i]) { | |
return burnFees[i]; | |
} | |
} | |
return burnFees[feeCycle.length]; | |
} | |
function setBurnFee(uint256 _index, uint256 fee) external onlyOwner { | |
require (fee <= 1000, "fee cannot exceed 1000"); | |
burnFees[_index] = fee; | |
} | |
function setBurnCycle(uint256 _index, uint256 _cycle) external onlyOwner { | |
feeCycle[_index] = _cycle; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment