Created
April 1, 2022 06:46
-
-
Save xtpor/88f15dcc7e7c6123c2d10b1e4ef56887 to your computer and use it in GitHub Desktop.
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.4; | |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | |
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
contract StakableToken is ERC20, Ownable { | |
constructor() ERC20("TestToken", "TT") { | |
_mint(msg.sender, 1000000 * 10 ** decimals()); | |
_lastUpdateTime = block.timestamp; | |
} | |
function mint(address to, uint256 amount) public onlyOwner { | |
_mint(to, amount); | |
} | |
struct Stake { | |
uint256 stakedAmount; | |
uint256 unclaimedReward; | |
uint256 cumulativeReturn; | |
} | |
uint256 _cumulativeReturn; | |
uint256 _lastUpdateTime; | |
mapping(address => Stake) _stakes; | |
function rate() public pure returns (uint256) { | |
return 1e18 * 1 / uint256(1 hours); | |
} | |
function stakeToken(uint256 amount) public { | |
_updateStakeReward(msg.sender); | |
Stake storage stake = _stakes[msg.sender]; | |
stake.stakedAmount += amount; | |
_transfer(msg.sender, address(this), amount); | |
} | |
function unstakeToken(uint256 amount) public { | |
_updateStakeReward(msg.sender); | |
Stake storage stake = _stakes[msg.sender]; | |
stake.stakedAmount -= amount; | |
_transfer(address(this), msg.sender, amount); | |
} | |
function claimReward() public { | |
_updateStakeReward(msg.sender); | |
Stake storage stake = _stakes[msg.sender]; | |
_mint(msg.sender, stake.unclaimedReward); | |
stake.unclaimedReward = 0; | |
} | |
function stakedAmount(address account) public view returns (uint256 reward) { | |
return _stakes[account].stakedAmount; | |
} | |
function unclaimedReward(address account) public view returns (uint256 reward) { | |
uint256 currentCumulativeReturn = _cumulativeReturn + (block.timestamp - _lastUpdateTime) * rate(); | |
Stake storage stake = _stakes[account]; | |
return stake.unclaimedReward + stake.stakedAmount * (currentCumulativeReturn - stake.cumulativeReturn) / 1e18; | |
} | |
function _updateCumulativeReturn() internal { | |
_cumulativeReturn += (block.timestamp - _lastUpdateTime) * rate(); | |
_lastUpdateTime = block.timestamp; | |
} | |
function _updateStakeReward(address account) internal { | |
_updateCumulativeReturn(); | |
Stake storage stake = _stakes[account]; | |
stake.unclaimedReward += stake.stakedAmount * (_cumulativeReturn - stake.cumulativeReturn) / 1e18; | |
stake.cumulativeReturn = _cumulativeReturn; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment