// SPDX-License-Identifier: UNLICENSED
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../common/OVLTokenTypes.sol";
interface IDeltaToken is IERC20 {
function vestingTransactions(address, uint256) external view returns (VestingTransaction memory);
function getUserInfo(address) external view returns (UserInformationLite memory);
function getMatureBalance(address, uint256) external view returns (uint256);
function liquidityRebasingPermitted() external view returns (bool);
function lpTokensInPair() external view returns (uint256);
function governance() external view returns (address);
function performLiquidityRebasing() external;
function distributor() external view returns (address);
function totalsForWallet(address ) external view returns (WalletTotals memory totals);
function adjustBalanceOfNoVestingAccount(address, uint256,bool) external;
function userInformation(address user) external view returns (UserInformation memory);
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// SPDX-License-Identifier: UNLICENSED
// DELTA-BUG-BOUNTY
pragma solidity ^0.7.6;
struct VestingTransaction {
uint256 amount;
uint256 fullVestingTimestamp;
}
struct WalletTotals {
uint256 mature;
uint256 immature;
uint256 total;
}
struct UserInformation {
// This is going to be read from only [0]
uint256 mostMatureTxIndex;
uint256 lastInTxIndex;
uint256 maturedBalance;
uint256 maxBalance;
bool fullSenderWhitelisted;
// Note that recieving immature balances doesnt mean they recieve them fully vested just that senders can do it
bool immatureReceiverWhitelisted;
bool noVestingWhitelisted;
}
struct UserInformationLite {
uint256 maturedBalance;
uint256 maxBalance;
uint256 mostMatureTxIndex;
uint256 lastInTxIndex;
}
struct VestingTransactionDetailed {
uint256 amount;
uint256 fullVestingTimestamp;
// uint256 percentVestedE4;
uint256 mature;
uint256 immature;
}
uint256 constant QTY_EPOCHS = 7;
uint256 constant SECONDS_PER_EPOCH = 172800; // About 2days
uint256 constant FULL_EPOCH_TIME = SECONDS_PER_EPOCH * QTY_EPOCHS;
// Precision Multiplier -- this many zeros (23) seems to get all the precision needed for all 18 decimals to be only off by a max of 1 unit
uint256 constant PM = 1e23;
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @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) {
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, reverting 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) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting 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) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* 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);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* 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) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* 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;
}
}
// SPDX-License-Identifier: UNLICENSED
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.6;
import "../../common/OVLTokenTypes.sol";
import "../libs/SafeMath.sol";
import "../../interfaces/IDeltaToken.sol";
contract TeamShareTimelock {
using SafeMath for uint256;
IDeltaToken immutable public DELTA_TOKEN;
uint256 constant private TOTAL_EXPECTED_AMOUNT = 225_000 ether;
/// @dev first month is paid out at the start
uint256 constant private INITIAL_CLAIM = 18_750 ether;
uint256 constant private VESTING_AMOUNT = TOTAL_EXPECTED_AMOUNT - INITIAL_CLAIM;
/// @dev 11 months since we advance the first month so it starts
/// vesting after 30 days for 11 months.
uint256 constant public TOTAL_VESTING_TIME = 330 days;
address immutable public TO;
uint256 public vestingStartTimestamp;
uint256 public vestingEndTimestamp;
uint256 public totalClaimed;
constructor(address _deltaToken, address _to) {
DELTA_TOKEN = IDeltaToken(_deltaToken);
TO = _to;
}
function initialize() public {
require(vestingStartTimestamp == 0, 'ALREADY_INITIALIZED');
DELTA_TOKEN.transferFrom(msg.sender, address(this), TOTAL_EXPECTED_AMOUNT);
require(DELTA_TOKEN.balanceOf(address(this)) == TOTAL_EXPECTED_AMOUNT, 'INSUFFICIENT_AMOUNT');
// Verify whitelistings
UserInformation memory accountInfo = DELTA_TOKEN.userInformation(address(this));
require(accountInfo.noVestingWhitelisted == true, 'NOT_NOVESTING_WHITELISTED');
require(accountInfo.fullSenderWhitelisted == true, 'NOT_FULLSENDER_WHITELISTED');
// Start vesting after 1 month since we advanced the complete first month
vestingStartTimestamp = block.timestamp + 30 days;
// Vesting ends in 11 months after that
vestingEndTimestamp = vestingStartTimestamp + TOTAL_VESTING_TIME;
// send out the first month right away
DELTA_TOKEN.transfer(TO, INITIAL_CLAIM);
}
function claim() public {
require(msg.sender == TO, 'INVALID_SENDER');
// It should never be possible to transfer more
// than VESTING_AMOUNT (206250 DELTA tokens) from this contract.
require(totalClaimed < VESTING_AMOUNT, 'ALL_CLAIMED');
uint256 claimed = claimable();
DELTA_TOKEN.transfer(TO, claimed);
totalClaimed = totalClaimed.add(claimed);
}
function claimable() public view returns (uint256) {
// Nothing claimable prior to the first month since we send an advance the first
// one and don't report any claimable when it's all claimed already.
// This, to ensure the contract is not used to fullSend arbitrary delta tokens.
if(block.timestamp < vestingStartTimestamp || totalClaimed >= VESTING_AMOUNT) {
return 0;
}
// Vesting has ended, send-out all the balance
if (block.timestamp >= vestingEndTimestamp) {
return DELTA_TOKEN.balanceOf(address(this));
}
uint256 secondsSinceVestingStarted = block.timestamp - vestingStartTimestamp;
return VESTING_AMOUNT.mul(secondsSinceVestingStarted).div(TOTAL_VESTING_TIME).sub(totalClaimed);
}
receive() external payable {
revert();
}
}
{
"compilationTarget": {
"contracts/v076/Team/TeamShareTimelock.sol": "TeamShareTimelock"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_deltaToken","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DELTA_TOKEN","outputs":[{"internalType":"contract IDeltaToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_VESTING_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingEndTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]