Files
dodo-contractV2/contracts/CrowdPooling/impl/CPVesting.sol

136 lines
4.4 KiB
Solidity
Raw Normal View History

2020-12-11 22:52:00 +08:00
/*
Copyright 2020 DODO ZOO.
SPDX-License-Identifier: Apache-2.0
*/
pragma solidity 0.6.9;
pragma experimental ABIEncoderV2;
import {SafeMath} from "../../lib/SafeMath.sol";
import {DecimalMath} from "../../lib/DecimalMath.sol";
import {Ownable} from "../../lib/Ownable.sol";
import {SafeERC20} from "../../lib/SafeERC20.sol";
import {IERC20} from "../../intf/IERC20.sol";
2020-12-12 15:53:42 +08:00
import {CPFunding} from "./CPFunding.sol";
2021-01-08 17:41:36 +08:00
import {IDODOCallee} from "../../intf/IDODOCallee.sol";
2020-12-11 22:52:00 +08:00
/**
2020-12-12 15:53:42 +08:00
* @title CPVesting
2020-12-11 22:52:00 +08:00
* @author DODO Breeder
*
* @notice Lock Token and release it linearly
*/
2020-12-12 15:53:42 +08:00
contract CPVesting is CPFunding {
2020-12-11 22:52:00 +08:00
using SafeMath for uint256;
using SafeERC20 for IERC20;
2021-01-18 22:32:12 +08:00
// ============ Events ============
2021-11-29 17:19:41 +08:00
event ClaimBaseToken(address user, uint256 baseAmount);
event ClaimQuoteToken(address user, uint256 quoteAmount);
2021-01-18 22:32:12 +08:00
event ClaimLP(uint256 amount);
// ================ Modifiers ================
2020-12-11 22:52:00 +08:00
modifier afterSettlement() {
require(_SETTLED_, "NOT_SETTLED");
_;
}
2021-11-29 17:19:41 +08:00
modifier afterFreeze() {
require(_SETTLED_ && block.timestamp >= _SETTLED_TIME_.add(_FREEZE_DURATION_), "FREEZED");
2021-11-09 21:05:54 +08:00
_;
}
2021-11-29 17:19:41 +08:00
modifier afterClaimFreeze() {
require(_SETTLED_ && block.timestamp >= _SETTLED_TIME_.add(_TOKEN_CLAIM_DURATION_), "CLAIM_FREEZED");
2020-12-18 18:31:45 +08:00
_;
}
2020-12-18 16:08:02 +08:00
// ============ Bidder Functions ============
2020-12-11 22:52:00 +08:00
2021-12-23 18:13:04 +08:00
function bidderClaim(address to, bytes calldata data) external {
if(_SETTLED_) {
_claimQuoteToken(to, data);
}
if(_SETTLED_ && block.timestamp >= _SETTLED_TIME_.add(_TOKEN_CLAIM_DURATION_)) {
_claimBaseToken(to);
}
}
function _claimQuoteToken(address to,bytes calldata data) internal {
// require(!_CLAIMED_QUOTE_[msg.sender], "ALREADY_CLAIMED_FUND");
if(_CLAIMED_QUOTE_[msg.sender]) return;
2021-11-29 17:19:41 +08:00
_CLAIMED_QUOTE_[msg.sender] = true;
2020-12-11 22:52:00 +08:00
2021-01-08 17:41:36 +08:00
uint256 quoteAmount = _UNUSED_QUOTE_.mul(_SHARES_[msg.sender]).div(_TOTAL_SHARES_);
_transferQuoteOut(to, quoteAmount);
if(data.length>0){
2021-11-29 17:19:41 +08:00
IDODOCallee(to).CPClaimBidCall(msg.sender,0,quoteAmount,data);
2021-01-08 17:41:36 +08:00
}
2021-11-29 17:19:41 +08:00
emit ClaimQuoteToken(msg.sender, quoteAmount);
}
2021-12-23 18:13:04 +08:00
function _claimBaseToken(address to) internal {
2021-11-29 17:19:41 +08:00
uint256 claimableBaseAmount = getClaimableBaseToken(msg.sender);
_CLAIMED_BASE_TOKEN_[msg.sender] = _CLAIMED_BASE_TOKEN_[msg.sender].add(claimableBaseAmount);
2021-12-27 21:40:32 +08:00
_transferBaseOut(to, claimableBaseAmount);
2021-11-29 17:19:41 +08:00
emit ClaimBaseToken(msg.sender, claimableBaseAmount);
}
function getClaimableBaseToken(address user) public view afterClaimFreeze returns (uint256) {
uint256 baseTotalAmount = _UNUSED_BASE_.mul(_SHARES_[user]).div(_TOTAL_SHARES_);
uint256 remainingBaseToken = DecimalMath.mulFloor(
getRemainingBaseTokenRatio(block.timestamp),
baseTotalAmount
);
return baseTotalAmount.sub(remainingBaseToken).sub(_CLAIMED_BASE_TOKEN_[user]);
}
function getRemainingBaseTokenRatio(uint256 timestamp) public view afterClaimFreeze returns (uint256) {
uint256 timePast = timestamp.sub(_SETTLED_TIME_.add(_TOKEN_CLAIM_DURATION_));
if (timePast < _TOKEN_VESTING_DURATION_) {
uint256 remainingTime = _TOKEN_VESTING_DURATION_.sub(timePast);
return DecimalMath.ONE.sub(_TOKEN_CLIFF_RATE_).mul(remainingTime).div(_TOKEN_VESTING_DURATION_);
} else {
return 0;
}
2020-12-11 22:52:00 +08:00
}
2020-12-18 16:08:02 +08:00
// ============ Owner Functions ============
2020-12-18 18:31:45 +08:00
function claimLPToken() external onlyOwner afterFreeze {
2021-01-18 22:32:12 +08:00
uint256 lpAmount = getClaimableLPToken();
IERC20(_POOL_).safeTransfer(_OWNER_, lpAmount);
emit ClaimLP(lpAmount);
2020-12-18 16:08:02 +08:00
}
2020-12-18 18:31:45 +08:00
function getClaimableLPToken() public view afterFreeze returns (uint256) {
2020-12-18 16:08:02 +08:00
uint256 remainingLPToken = DecimalMath.mulFloor(
getRemainingLPRatio(block.timestamp),
_TOTAL_LP_AMOUNT_
);
return IERC20(_POOL_).balanceOf(address(this)).sub(remainingLPToken);
2020-12-11 22:52:00 +08:00
}
2020-12-18 18:31:45 +08:00
function getRemainingLPRatio(uint256 timestamp) public view afterFreeze returns (uint256) {
uint256 timePast = timestamp.sub(_SETTLED_TIME_.add(_FREEZE_DURATION_));
2020-12-18 16:08:02 +08:00
if (timePast < _VESTING_DURATION_) {
uint256 remainingTime = _VESTING_DURATION_.sub(timePast);
return DecimalMath.ONE.sub(_CLIFF_RATE_).mul(remainingTime).div(_VESTING_DURATION_);
} else {
return 0;
}
2020-12-11 22:52:00 +08:00
}
}