some changes on MineV2
This commit is contained in:
1
cn
Submodule
1
cn
Submodule
Submodule cn added at dde6d47d3b
@@ -14,24 +14,21 @@ import {DecimalMath} from "../../lib/DecimalMath.sol";
|
||||
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
|
||||
import {IRewardVault, RewardVault} from "./RewardVault.sol";
|
||||
|
||||
|
||||
contract BaseMine is InitializableOwnable {
|
||||
using SafeERC20 for IERC20;
|
||||
using SafeMath for uint256;
|
||||
|
||||
// ============ Storage ============
|
||||
|
||||
|
||||
struct RewardTokenInfo {
|
||||
address rewardToken;
|
||||
uint256 startBlock;
|
||||
uint256 endBlock;
|
||||
address rewardVault;
|
||||
|
||||
uint256 rewardPerBlock;
|
||||
uint256 accRewardPerShare;
|
||||
uint256 lastRewardBlock;
|
||||
|
||||
mapping(address => uint256) userRewardPerTokenPaid;
|
||||
mapping(address => uint256) userRewardPerSharePaid;
|
||||
mapping(address => uint256) userRewards;
|
||||
}
|
||||
|
||||
@@ -50,54 +47,19 @@ contract BaseMine is InitializableOwnable {
|
||||
|
||||
// ============ Modifier ==========
|
||||
|
||||
modifier updateReward(address user) {
|
||||
uint256 len = rewardTokenInfos.length;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
RewardTokenInfo storage rt = rewardTokenInfos[i];
|
||||
rt.accRewardPerShare = rewardPerToken(i);
|
||||
rt.lastRewardBlock = lastBlockRewardApplicable(i);
|
||||
if (user != address(0)) {
|
||||
rt.userRewards[user] = getPendingReward(i, user);
|
||||
rt.userRewardPerTokenPaid[user] = rt.accRewardPerShare;
|
||||
}
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
// ============ View ============
|
||||
|
||||
function lastBlockRewardApplicable(uint i) public view returns (uint256) {
|
||||
uint256 startBlock = rewardTokenInfos[i].startBlock;
|
||||
uint256 endBlock = rewardTokenInfos[i].endBlock;
|
||||
if(block.number < endBlock) {
|
||||
if(block.number < startBlock)
|
||||
return startBlock;
|
||||
else
|
||||
return block.number;
|
||||
}else {
|
||||
return endBlock;
|
||||
}
|
||||
}
|
||||
|
||||
function rewardPerToken(uint i) public view returns (uint256) {
|
||||
function getPendingReward(address user, uint256 i) public view returns (uint256) {
|
||||
RewardTokenInfo memory rt = rewardTokenInfos[i];
|
||||
if (totalSupply() == 0) {
|
||||
return rt.accRewardPerShare;
|
||||
uint256 accRewardPerShare = rt.accRewardPerShare;
|
||||
if (rt.lastRewardBlock != block.number) {
|
||||
accRewardPerShare = _getAccRewardPerShare(i)
|
||||
}
|
||||
return rt.accRewardPerShare.add(
|
||||
DecimalMath.divFloor(
|
||||
lastBlockRewardApplicable(i).sub(rt.lastRewardBlock).mul(rt.rewardPerBlock),
|
||||
totalSupply()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getPendingReward(uint i, address user) public view returns (uint256) {
|
||||
RewardTokenInfo storage rt = rewardTokenInfos[i];
|
||||
return DecimalMath.mulFloor(
|
||||
balanceOf(user),
|
||||
rewardPerToken(i).sub(rt.userRewardPerTokenPaid[user])
|
||||
).add(rt.userRewards[user]);
|
||||
return
|
||||
DecimalMath.mulFloor(
|
||||
balanceOf(user),
|
||||
accRewardPerShare.sub(rt.userRewardPeSharenPaid[user])
|
||||
).add(rt.userRewards[user]);
|
||||
}
|
||||
|
||||
function totalSupply() public view returns (uint256) {
|
||||
@@ -108,14 +70,26 @@ contract BaseMine is InitializableOwnable {
|
||||
return _balances[user];
|
||||
}
|
||||
|
||||
function getRewardTokenByIdx(uint i) public view returns (address) {
|
||||
function getRewardTokenById(uint256 i) public view returns (address) {
|
||||
require(i<rewardTokenInfos.length, "DODOMineV2: REWARD_ID_FOUND");
|
||||
RewardTokenInfo memory rt = rewardTokenInfos[i];
|
||||
return rt.rewardToken;
|
||||
}
|
||||
|
||||
function getIdByRewardToken(address rewardToken) public view returns(uint256) {
|
||||
uint256 len = rewardTokenInfos.length;
|
||||
for (uint256 i = 0; i < len; i++) {
|
||||
if (rewardToken == rewardTokenInfos[i].rewardToken) {
|
||||
return i;
|
||||
};
|
||||
}
|
||||
require(true, "DODOMineV2: TOKEN_NOT_FOUND");
|
||||
}
|
||||
|
||||
// ============ Claim ============
|
||||
|
||||
function getReward(uint i) public updateReward(msg.sender) {
|
||||
function claimReward(uint256 i) public {
|
||||
_updateReward(msg.sender, i);
|
||||
RewardTokenInfo storage rt = rewardTokenInfos[i];
|
||||
uint256 reward = rt.userRewards[msg.sender];
|
||||
if (reward > 0) {
|
||||
@@ -125,23 +99,30 @@ contract BaseMine is InitializableOwnable {
|
||||
}
|
||||
}
|
||||
|
||||
function getAllRewards() public {
|
||||
function claimAllRewards() public {
|
||||
uint256 len = rewardTokenInfos.length;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
getReward(i);
|
||||
for (uint256 i = 0; i < len; i++) {
|
||||
claimReward(i);
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Ownable ================
|
||||
|
||||
function addRewardToken(address rewardToken, uint256 startBlock, uint256 endBlock) external onlyOwner {
|
||||
require(rewardToken != address(0),"DODOMineV2: TOKEN_INVALID");
|
||||
function addRewardToken(
|
||||
address rewardToken,
|
||||
uint256 startBlock,
|
||||
uint256 endBlock
|
||||
) external onlyOwner {
|
||||
require(rewardToken != address(0), "DODOMineV2: TOKEN_INVALID");
|
||||
require(startBlock > block.number, "DODOMineV2: START_BLOCK_INVALID");
|
||||
require(endBlock > startBlock ,"DODOMineV2: DURATION_INVALID");
|
||||
require(endBlock > startBlock, "DODOMineV2: DURATION_INVALID");
|
||||
|
||||
uint256 len = rewardTokenInfos.length;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
require(rewardToken != rewardTokenInfos[i].rewardToken, "DODOMineV2: TOKEN_ALREADY_ADDED");
|
||||
for (uint256 i = 0; i < len; i++) {
|
||||
require(
|
||||
rewardToken != rewardTokenInfos[i].rewardToken,
|
||||
"DODOMineV2: TOKEN_ALREADY_ADDED"
|
||||
);
|
||||
}
|
||||
|
||||
RewardTokenInfo storage rt = rewardTokenInfos.push();
|
||||
@@ -165,21 +146,72 @@ contract BaseMine is InitializableOwnable {
|
||||
}
|
||||
}
|
||||
|
||||
function setEndBlock(uint i, uint256 newEndBlock) external onlyOwner updateReward(address(0)) {
|
||||
require(block.number < newEndBlock, "DODOMineV2: END_BLOCK_INVALID");
|
||||
function setEndBlock(uint256 i, uint256 newEndBlock)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
_updateReward(address(0), i);
|
||||
RewardTokenInfo storage rt = rewardTokenInfos[i];
|
||||
|
||||
require(block.number < newEndBlock, "DODOMineV2: END_BLOCK_INVALID");
|
||||
require(block.number > rt.startBlock, "DODOMineV2: NOT_START");
|
||||
require(block.number < rt.endBlock, "DODOMineV2: ALREADY_CLOSE");
|
||||
|
||||
rt.endBlock = newEndBlock;
|
||||
rt.lastRewardBlock = block.number;
|
||||
emit UpdateEndBlock(i, newEndBlock);
|
||||
}
|
||||
|
||||
function setReward(uint i, uint256 newRewardPerBlock) external onlyOwner updateReward(address(0)) {
|
||||
function setReward(uint256 i, uint256 newRewardPerBlock)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
_updateReward(address(0), i);
|
||||
RewardTokenInfo storage rt = rewardTokenInfos[i];
|
||||
uint256 endBlock = rt.endBlock;
|
||||
require(block.number < endBlock, "DODOMineV2: ALREADY_FINISHED");
|
||||
rt.rewardPerBlock = newRewardPerBlock;
|
||||
emit UpdateReward(i, newRewardPerBlock);
|
||||
}
|
||||
|
||||
|
||||
// ============ Internal ============
|
||||
|
||||
function _updateReward(address user, uint256 i) internal {
|
||||
RewardTokenInfo storage rt = rewardTokenInfos[i];
|
||||
if (rt.lastRewardBlock != block.number){
|
||||
rt.accRewardPerShare = _getAccRewardPerShare(i);
|
||||
rt.lastRewardBlock = block.number;
|
||||
}
|
||||
if (user != address(0)) {
|
||||
rt.userRewards[user] = getPendingReward(user, i);
|
||||
rt.userRewardPerSharePaid[user] = rt.accRewardPerShare;
|
||||
}
|
||||
}
|
||||
|
||||
function _updateAllReward(address user) internal {
|
||||
uint256 len = rewardTokenInfos.length;
|
||||
for (uint256 i = 0; i < len; i++) {
|
||||
_updateReward(user, i);
|
||||
}
|
||||
}
|
||||
|
||||
function _getUnrewardBlockNum(uint256 i) internal view returns (uint256) {
|
||||
RewardTokenInfo memory rt = rewardTokenInfos[i];
|
||||
if (block.number < rt.startBlock || rt.lastRewardBlock > rt.endBlock) {
|
||||
return 0;
|
||||
}
|
||||
uint256 start = rt.startBlock > block.number ? rt.startBlock : block.number;
|
||||
uint256 end = rt.endBlock < block.number ? rt.endBlock : block.number;
|
||||
return end.sub(start);
|
||||
}
|
||||
|
||||
function _getAccRewardPerShare(uint256 i) internal view returns (uint256) {
|
||||
RewardTokenInfo memory rt = rewardTokenInfos[i];
|
||||
if (totalSupply() == 0) {
|
||||
return rt.accRewardPerShare;
|
||||
}
|
||||
return
|
||||
rt.accRewardPerShare.add(
|
||||
DecimalMath.divFloor(_getUnrewardBlockNum(i).mul(rt.rewardPerBlock), totalSupply())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ contract ERC20Mine is BaseMine {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// ============ Storage ============
|
||||
|
||||
|
||||
address public immutable _TOKEN_;
|
||||
|
||||
constructor(address token) public {
|
||||
@@ -25,34 +25,31 @@ contract ERC20Mine is BaseMine {
|
||||
}
|
||||
|
||||
// ============ Event ============
|
||||
|
||||
event Deposit(address indexed user, uint256 amount);
|
||||
event Withdraw(address indexed user, uint256 amount);
|
||||
|
||||
|
||||
// ============ Deposit && Withdraw && Exit ============
|
||||
|
||||
function deposit(uint256 amount) virtual public updateReward(msg.sender) {
|
||||
function deposit(uint256 amount) public {
|
||||
require(amount > 0, "DODOMineV2: CANNOT_DEPOSIT_ZERO");
|
||||
|
||||
_updateAllReward(msg.sender);
|
||||
_totalSupply = _totalSupply.add(amount);
|
||||
_balances[msg.sender] = _balances[msg.sender].add(amount);
|
||||
IERC20(_TOKEN_).safeTransferFrom(msg.sender, address(this), amount);
|
||||
|
||||
emit Deposit(msg.sender, amount);
|
||||
}
|
||||
|
||||
function withdraw(uint256 amount) virtual public updateReward(msg.sender) {
|
||||
function withdraw(uint256 amount) public {
|
||||
require(amount > 0, "DODOMineV2: CANNOT_WITHDRAW_ZERO");
|
||||
|
||||
_updateAllReward(msg.sender);
|
||||
_totalSupply = _totalSupply.sub(amount);
|
||||
_balances[msg.sender] = _balances[msg.sender].sub(amount);
|
||||
IERC20(_TOKEN_).safeTransfer(msg.sender, amount);
|
||||
|
||||
emit Withdraw(msg.sender, amount);
|
||||
}
|
||||
|
||||
function withdrawAll() external {
|
||||
withdraw(balanceOf(msg.sender));
|
||||
}
|
||||
|
||||
function exit() external {
|
||||
withdraw(balanceOf(msg.sender));
|
||||
getAllRewards();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,10 @@ contract vDODOMine is BaseMine {
|
||||
|
||||
function deposit(uint256 amount) public {
|
||||
require(amount > 0, "vDODOMineETH: CANNOT_DEPOSIT_ZERO");
|
||||
require(IVDODOToken(_vDODO_TOKEN_).availableBalanceOf(msg.sender) >= amount, "vDODOMineETH: vDODO_NOT_ENOUGH");
|
||||
require(
|
||||
amount <= IVDODOToken(_vDODO_TOKEN_).availableBalanceOf(msg.sender),
|
||||
"vDODOMineETH: vDODO_NOT_ENOUGH"
|
||||
);
|
||||
_totalSupply = _totalSupply.add(amount);
|
||||
_balances[msg.sender] = _balances[msg.sender].add(amount);
|
||||
emit Deposit(msg.sender, amount);
|
||||
@@ -44,39 +47,30 @@ contract vDODOMine is BaseMine {
|
||||
|
||||
function withdraw(uint256 amount) public {
|
||||
require(amount > 0, "DODOMineV2: CANNOT_WITHDRAW_ZERO");
|
||||
require(amount <= _balances[msg.sender], "DODOMineV2: WITHDRAW_BALANCE_NOT_ENOUGH");
|
||||
_totalSupply = _totalSupply.sub(amount);
|
||||
_balances[msg.sender] = _balances[msg.sender].sub(amount);
|
||||
emit Withdraw(msg.sender, amount);
|
||||
}
|
||||
|
||||
function withdrawAll() external {
|
||||
withdraw(balanceOf(msg.sender));
|
||||
}
|
||||
|
||||
function exit() external {
|
||||
withdraw(balanceOf(msg.sender));
|
||||
getAllRewards();
|
||||
}
|
||||
|
||||
// ============ View ============
|
||||
|
||||
function getLockedvDODO(address account) external view returns (uint256) {
|
||||
return balanceOf(account);
|
||||
}
|
||||
|
||||
|
||||
// =============== Ownable ================
|
||||
|
||||
function syncBalance(address[] calldata accountList, uint256[] calldata amountList) external onlyOwner {
|
||||
require(accountList.length == amountList.length, "DODOMineV2: LENGTH_NOT_MATCH");
|
||||
for (uint256 i = 0; i < accountList.length; ++i) {
|
||||
uint256 curBalance = balanceOf(accountList[i]);
|
||||
if(curBalance > amountList[i]) {
|
||||
uint256 subAmount = curBalance.sub(amountList[i]);
|
||||
_totalSupply = _totalSupply.sub(subAmount);
|
||||
_balances[accountList[i]] = amountList[i];
|
||||
function syncBalance(address[] calldata userList) external onlyOwner {
|
||||
for (uint256 i = 0; i < userList.length; ++i) {
|
||||
address user = userList[i];
|
||||
uint256 curBalance = balanceOf(user);
|
||||
uint256 vDODOBalance = IERC20(_vDODO_TOKEN_).balanceOf(user);
|
||||
if (curBalance > vDODOBalance) {
|
||||
_updateAllReward(user);
|
||||
_totalSupply = _totalSupply.add(vDODOBalance).sub(curBalance);
|
||||
_balances[user] = vDODOBalance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user